001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2015 ForgeRock AS. 026 */ 027package org.forgerock.opendj.config; 028 029import java.util.Arrays; 030import java.util.HashSet; 031import java.util.LinkedList; 032import java.util.List; 033import java.util.MissingResourceException; 034import java.util.NoSuchElementException; 035import java.util.Set; 036 037/** 038 * This class is used to map configuration elements to their LDAP schema names. 039 * <p> 040 * It is possible to augment the core LDAP profile with additional profile 041 * mappings at run-time using instances of {@link Wrapper}. This is useful for 042 * unit tests which need to add and remove mock components. 043 */ 044public final class LDAPProfile { 045 046 /** 047 * LDAP profile wrappers can be used to provide temporary LDAP profile 048 * information for components which do not have LDAP profile property files. 049 * These components are typically "mock" components used in unit-tests. 050 */ 051 public static abstract class Wrapper { 052 053 /** Default constructor. */ 054 protected Wrapper() { 055 // No implementation required. 056 } 057 058 /** 059 * Get the name of the LDAP attribute associated with the specified 060 * property definition. 061 * <p> 062 * The default implementation of this method is to return 063 * <code>null</code>. 064 * 065 * @param d 066 * The managed object definition. 067 * @param pd 068 * The property definition. 069 * @return Returns the name of the LDAP attribute associated with the 070 * specified property definition, or <code>null</code> if the 071 * property definition is not handled by this LDAP profile 072 * wrapper. 073 */ 074 public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd) { 075 return null; 076 } 077 078 /** 079 * Gets the LDAP RDN attribute type for child entries of an instantiable 080 * relation. 081 * <p> 082 * The default implementation of this method is to return 083 * <code>null</code>. 084 * 085 * @param r 086 * The instantiable relation. 087 * @return Returns the LDAP RDN attribute type for child entries of an 088 * instantiable relation, or <code>null</code> if the 089 * instantiable relation is not handled by this LDAP profile 090 * wrapper. 091 */ 092 public String getRelationChildRDNType(InstantiableRelationDefinition<?, ?> r) { 093 return null; 094 } 095 096 /** 097 * Gets the LDAP RDN attribute type for child entries of an set 098 * relation. 099 * <p> 100 * The default implementation of this method is to return 101 * <code>null</code>. 102 * 103 * @param r 104 * The set relation. 105 * @return Returns the LDAP RDN attribute type for child entries of an 106 * set relation, or <code>null</code> if the set relation is not 107 * handled by this LDAP profile wrapper. 108 */ 109 public String getRelationChildRDNType(SetRelationDefinition<?, ?> r) { 110 return null; 111 } 112 113 /** 114 * Get the principle object class associated with the specified 115 * definition. 116 * <p> 117 * The default implementation of this method is to return 118 * <code>null</code>. 119 * 120 * @param d 121 * The managed object definition. 122 * @return Returns the principle object class associated with the 123 * specified definition, or <code>null</code> if the managed 124 * object definition is not handled by this LDAP profile 125 * wrapper. 126 */ 127 public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) { 128 return null; 129 } 130 131 /** 132 * Get an LDAP RDN sequence associatied with a relation. 133 * <p> 134 * The default implementation of this method is to return 135 * <code>null</code>. 136 * 137 * @param r 138 * The relation. 139 * @return Returns the LDAP RDN sequence associatied with a relation, or 140 * <code>null</code> if the relation is not handled by this LDAP 141 * profile wrapper. 142 */ 143 public String getRelationRDNSequence(RelationDefinition<?, ?> r) { 144 return null; 145 } 146 } 147 148 /** The singleton instance. */ 149 private static final LDAPProfile INSTANCE = new LDAPProfile(); 150 151 /** 152 * Get the global LDAP profile instance. 153 * 154 * @return Returns the global LDAP profile instance. 155 */ 156 public static LDAPProfile getInstance() { 157 return INSTANCE; 158 } 159 160 /** The list of profile wrappers. */ 161 private final LinkedList<Wrapper> profiles = new LinkedList<>(); 162 163 /** The LDAP profile property table. */ 164 private final ManagedObjectDefinitionResource resource = ManagedObjectDefinitionResource.createForProfile("ldap"); 165 166 /** Prevent construction. */ 167 private LDAPProfile() { 168 // No implementation required. 169 } 170 171 /** 172 * Get the name of the LDAP attribute associated with the specified property 173 * definition. 174 * 175 * @param d 176 * The managed object definition. 177 * @param pd 178 * The property definition. 179 * @return Returns the name of the LDAP attribute associated with the 180 * specified property definition. 181 * @throws MissingResourceException 182 * If the LDAP profile properties file associated with the 183 * provided managed object definition could not be loaded. 184 */ 185 public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd) { 186 for (Wrapper profile : profiles) { 187 String attributeName = profile.getAttributeName(d, pd); 188 if (attributeName != null) { 189 return attributeName; 190 } 191 } 192 return resource.getString(d, "attribute." + pd.getName()); 193 } 194 195 /** 196 * Gets the LDAP RDN attribute type for child entries of an instantiable 197 * relation. 198 * 199 * @param r 200 * The instantiable relation. 201 * @return Returns the LDAP RDN attribute type for child entries of an 202 * instantiable relation. 203 * @throws MissingResourceException 204 * If the LDAP profile properties file associated with the 205 * provided managed object definition could not be loaded. 206 */ 207 public String getRelationChildRDNType(InstantiableRelationDefinition<?, ?> r) { 208 if (r.getNamingPropertyDefinition() != null) { 209 // Use the attribute associated with the naming property. 210 return getAttributeName(r.getChildDefinition(), r.getNamingPropertyDefinition()); 211 } else { 212 for (Wrapper profile : profiles) { 213 String rdnType = profile.getRelationChildRDNType(r); 214 if (rdnType != null) { 215 return rdnType; 216 } 217 } 218 return resource.getString(r.getParentDefinition(), "naming-attribute." + r.getName()); 219 } 220 } 221 222 /** 223 * Gets the LDAP object classes associated with an instantiable or set 224 * relation branch. The branch is the parent entry of child managed objects. 225 * 226 * @param r 227 * The instantiable or set relation. 228 * @return Returns the LDAP object classes associated with an instantiable 229 * or set relation branch. 230 */ 231 public List<String> getRelationObjectClasses(RelationDefinition<?, ?> r) { 232 return Arrays.asList(new String[] { "top", "ds-cfg-branch" }); 233 } 234 235 /** 236 * Gets the LDAP RDN attribute type for child entries of an set relation. 237 * 238 * @param r 239 * The set relation. 240 * @return Returns the LDAP RDN attribute type for child entries of an set 241 * relation. 242 * @throws MissingResourceException 243 * If the LDAP profile properties file associated with the 244 * provided managed object definition could not be loaded. 245 */ 246 public String getRelationChildRDNType(SetRelationDefinition<?, ?> r) { 247 for (Wrapper profile : profiles) { 248 String rdnType = profile.getRelationChildRDNType(r); 249 if (rdnType != null) { 250 return rdnType; 251 } 252 } 253 return resource.getString(r.getParentDefinition(), "naming-attribute." + r.getName()); 254 } 255 256 /** 257 * Get the principle object class associated with the specified definition. 258 * 259 * @param d 260 * The managed object definition. 261 * @return Returns the principle object class associated with the specified 262 * definition. 263 * @throws MissingResourceException 264 * If the LDAP profile properties file associated with the 265 * provided managed object definition could not be loaded. 266 */ 267 public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) { 268 if (d.isTop()) { 269 return "top"; 270 } 271 272 for (Wrapper profile : profiles) { 273 String objectClass = profile.getObjectClass(d); 274 if (objectClass != null) { 275 return objectClass; 276 } 277 } 278 return resource.getString(d, "objectclass"); 279 } 280 281 /** 282 * Get all the object classes associated with the specified definition. 283 * <p> 284 * The returned list is ordered such that the uppermost object classes 285 * appear first (e.g. top). 286 * 287 * @param d 288 * The managed object definition. 289 * @return Returns all the object classes associated with the specified 290 * definition. 291 * @throws MissingResourceException 292 * If the LDAP profile properties file associated with the 293 * provided managed object definition could not be loaded. 294 */ 295 public List<String> getObjectClasses(AbstractManagedObjectDefinition<?, ?> d) { 296 LinkedList<String> objectClasses = new LinkedList<>(); 297 Set<String> s = new HashSet<>(); 298 299 // Add the object classes from the parent hierarchy. 300 while (d != null) { 301 String oc = getObjectClass(d); 302 if (s.add(oc)) { 303 objectClasses.addFirst(oc); 304 } 305 d = d.getParent(); 306 } 307 308 if (!s.contains("top")) { 309 objectClasses.addFirst("top"); 310 } 311 312 return objectClasses; 313 } 314 315 /** 316 * Get an LDAP RDN sequence associated with a relation. 317 * 318 * @param r 319 * The relation. 320 * @return Returns the LDAP RDN sequence associated with a relation. 321 * @throws MissingResourceException 322 * If the LDAP profile properties file associated with the 323 * provided managed object definition could not be loaded. 324 */ 325 public String getRelationRDNSequence(RelationDefinition<?, ?> r) { 326 for (Wrapper profile : profiles) { 327 String rdnSequence = profile.getRelationRDNSequence(r); 328 if (rdnSequence != null) { 329 return rdnSequence; 330 } 331 } 332 return resource.getString(r.getParentDefinition(), "rdn." + r.getName()); 333 } 334 335 /** 336 * Removes the last LDAP profile wrapper added using 337 * {@link #pushWrapper(org.forgerock.opendj.config.LDAPProfile.Wrapper)}. 338 * 339 * @throws NoSuchElementException 340 * If there are no LDAP profile wrappers. 341 */ 342 public void popWrapper() { 343 profiles.removeFirst(); 344 } 345 346 /** 347 * Decorates the core LDAP profile with the provided LDAP profile wrapper. 348 * All profile requests will be directed to the provided wrapper before 349 * being forwarded onto the core profile if the request could not be 350 * satisfied. 351 * 352 * @param wrapper 353 * The LDAP profile wrapper. 354 */ 355 public void pushWrapper(Wrapper wrapper) { 356 profiles.addFirst(wrapper); 357 } 358}