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 */ 027 028package org.opends.server.admin; 029 030 031 032import java.util.Arrays; 033import java.util.HashSet; 034import java.util.LinkedList; 035import java.util.List; 036import java.util.MissingResourceException; 037import java.util.NoSuchElementException; 038import java.util.Set; 039 040 041 042/** 043 * This class is used to map configuration elements to their LDAP 044 * schema names. 045 * <p> 046 * It is possible to augment the core LDAP profile with additional 047 * profile mappings at run-time using instances of {@link Wrapper}. 048 * This is useful for unit tests which need to add and remove mock 049 * components. 050 */ 051public final class LDAPProfile { 052 053 /** 054 * LDAP profile wrappers can be used to provide temporary LDAP 055 * profile information for components which do not have LDAP profile 056 * property files. These components are typically "mock" components 057 * used in unit-tests. 058 */ 059 public static abstract class Wrapper { 060 061 /** 062 * Default constructor. 063 */ 064 protected Wrapper() { 065 // No implementation required. 066 } 067 068 069 070 /** 071 * Get the name of the LDAP attribute associated with the 072 * specified property definition. 073 * <p> 074 * The default implementation of this method is to return 075 * <code>null</code>. 076 * 077 * @param d 078 * The managed object definition. 079 * @param pd 080 * The property definition. 081 * @return Returns the name of the LDAP attribute associated with 082 * the specified property definition, or <code>null</code> 083 * if the property definition is not handled by this LDAP 084 * profile wrapper. 085 */ 086 public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d, 087 PropertyDefinition<?> pd) { 088 return null; 089 } 090 091 092 093 /** 094 * Gets the LDAP RDN attribute type for child entries of an 095 * instantiable relation. 096 * <p> 097 * The default implementation of this method is to return 098 * <code>null</code>. 099 * 100 * @param r 101 * The instantiable relation. 102 * @return Returns the LDAP RDN attribute type for child entries 103 * of an instantiable relation, or <code>null</code> if 104 * the instantiable relation is not handled by this LDAP 105 * profile wrapper. 106 */ 107 public String getRelationChildRDNType( 108 InstantiableRelationDefinition<?, ?> r) { 109 return null; 110 } 111 112 113 114 /** 115 * Gets the LDAP RDN attribute type for child entries of an set 116 * relation. 117 * <p> 118 * The default implementation of this method is to return 119 * <code>null</code>. 120 * 121 * @param r 122 * The set relation. 123 * @return Returns the LDAP RDN attribute type for child entries of 124 * an set relation, or <code>null</code> if the set relation 125 * is not handled by this LDAP profile wrapper. 126 */ 127 public String getRelationChildRDNType(SetRelationDefinition<?, ?> r) 128 { 129 return null; 130 } 131 132 133 134 /** 135 * Get the principle object class associated with the specified 136 * definition. 137 * <p> 138 * The default implementation of this method is to return 139 * <code>null</code>. 140 * 141 * @param d 142 * The managed object definition. 143 * @return Returns the principle object class associated with the 144 * specified definition, or <code>null</code> if the 145 * managed object definition is not handled by this LDAP 146 * profile wrapper. 147 */ 148 public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) { 149 return null; 150 } 151 152 153 154 /** 155 * Get an LDAP RDN sequence associatied with a relation. 156 * <p> 157 * The default implementation of this method is to return 158 * <code>null</code>. 159 * 160 * @param r 161 * The relation. 162 * @return Returns the LDAP RDN sequence associatied with a 163 * relation, or <code>null</code> if the relation is not 164 * handled by this LDAP profile wrapper. 165 */ 166 public String getRelationRDNSequence(RelationDefinition<?, ?> r) { 167 return null; 168 } 169 } 170 171 /** The singleton instance. */ 172 private static final LDAPProfile INSTANCE = new LDAPProfile(); 173 174 175 176 /** 177 * Get the global LDAP profile instance. 178 * 179 * @return Returns the global LDAP profile instance. 180 */ 181 public static LDAPProfile getInstance() { 182 return INSTANCE; 183 } 184 185 /** The list of profile wrappers. */ 186 private final LinkedList<Wrapper> profiles = new LinkedList<>(); 187 188 /** The LDAP profile property table. */ 189 private final ManagedObjectDefinitionResource resource = 190 ManagedObjectDefinitionResource.createForProfile("ldap"); 191 192 193 194 /** Prevent construction. */ 195 private LDAPProfile() { 196 // No implementation required. 197 } 198 199 200 201 /** 202 * Get the name of the LDAP attribute associated with the specified 203 * property definition. 204 * 205 * @param d 206 * The managed object definition. 207 * @param pd 208 * The property definition. 209 * @return Returns the name of the LDAP attribute associated with 210 * the specified property definition. 211 * @throws MissingResourceException 212 * If the LDAP profile properties file associated with the 213 * provided managed object definition could not be loaded. 214 */ 215 public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d, 216 PropertyDefinition<?> pd) throws MissingResourceException { 217 for (Wrapper profile : profiles) { 218 String attributeName = profile.getAttributeName(d, pd); 219 if (attributeName != null) { 220 return attributeName; 221 } 222 } 223 return resource.getString(d, "attribute." + pd.getName()); 224 } 225 226 227 228 /** 229 * Gets the LDAP RDN attribute type for child entries of an 230 * instantiable relation. 231 * 232 * @param r 233 * The instantiable relation. 234 * @return Returns the LDAP RDN attribute type for child entries of 235 * an instantiable relation. 236 * @throws MissingResourceException 237 * If the LDAP profile properties file associated with the 238 * provided managed object definition could not be loaded. 239 */ 240 public String getRelationChildRDNType( 241 InstantiableRelationDefinition<?, ?> r) throws MissingResourceException { 242 if (r.getNamingPropertyDefinition() != null) { 243 // Use the attribute associated with the naming property. 244 return getAttributeName(r.getChildDefinition(), r 245 .getNamingPropertyDefinition()); 246 } else { 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." 254 + r.getName()); 255 } 256 } 257 258 259 260 /** 261 * Gets the LDAP object classes associated with an instantiable or set 262 * relation branch. The branch is the parent entry of child managed 263 * objects. 264 * 265 * @param r 266 * The instantiable or set relation. 267 * @return Returns the LDAP object classes associated with an 268 * instantiable or set relation branch. 269 */ 270 public List<String> getRelationObjectClasses( 271 RelationDefinition<?, ?> r) { 272 return Arrays.asList(new String[] { "top", "ds-cfg-branch" }); 273 } 274 275 276 277 /** 278 * Gets the LDAP RDN attribute type for child entries of an set 279 * relation. 280 * 281 * @param r 282 * The set relation. 283 * @return Returns the LDAP RDN attribute type for child entries of an 284 * set relation. 285 * @throws MissingResourceException 286 * If the LDAP profile properties file associated with the 287 * provided managed object definition could not be loaded. 288 */ 289 public String getRelationChildRDNType(SetRelationDefinition<?, ?> r) 290 throws MissingResourceException 291 { 292 for (Wrapper profile : profiles) 293 { 294 String rdnType = profile.getRelationChildRDNType(r); 295 if (rdnType != null) 296 { 297 return rdnType; 298 } 299 } 300 return resource.getString(r.getParentDefinition(), 301 "naming-attribute." + r.getName()); 302 } 303 304 305 306 /** 307 * Get the principle object class associated with the specified 308 * definition. 309 * 310 * @param d 311 * The managed object definition. 312 * @return Returns the principle object class associated with the 313 * specified definition. 314 * @throws MissingResourceException 315 * If the LDAP profile properties file associated with the 316 * provided managed object definition could not be loaded. 317 */ 318 public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) 319 throws MissingResourceException { 320 if (d.isTop()) { 321 return "top"; 322 } 323 324 for (Wrapper profile : profiles) { 325 String objectClass = profile.getObjectClass(d); 326 if (objectClass != null) { 327 return objectClass; 328 } 329 } 330 return resource.getString(d, "objectclass"); 331 } 332 333 334 335 /** 336 * Get all the object classes associated with the specified 337 * definition. 338 * <p> 339 * The returned list is ordered such that the uppermost object 340 * classes appear first (e.g. top). 341 * 342 * @param d 343 * The managed object definition. 344 * @return Returns all the object classes associated with the 345 * specified definition. 346 * @throws MissingResourceException 347 * If the LDAP profile properties file associated with the 348 * provided managed object definition could not be loaded. 349 */ 350 public List<String> getObjectClasses(AbstractManagedObjectDefinition<?, ?> d) 351 throws MissingResourceException { 352 LinkedList<String> objectClasses = new LinkedList<>(); 353 Set<String> s = new HashSet<>(); 354 355 // Add the object classes from the parent hierarchy. 356 while (d != null) { 357 String oc = getObjectClass(d); 358 if (!s.contains(oc)) { 359 objectClasses.addFirst(oc); 360 s.add(oc); 361 } 362 d = d.getParent(); 363 } 364 365 if (!s.contains("top")) { 366 objectClasses.addFirst("top"); 367 } 368 369 return objectClasses; 370 } 371 372 373 374 /** 375 * Get an LDAP RDN sequence associated with a relation. 376 * 377 * @param r 378 * The relation. 379 * @return Returns the LDAP RDN sequence associated with a 380 * relation. 381 * @throws MissingResourceException 382 * If the LDAP profile properties file associated with the 383 * provided managed object definition could not be loaded. 384 */ 385 public String getRelationRDNSequence(RelationDefinition<?, ?> r) 386 throws MissingResourceException { 387 for (Wrapper profile : profiles) { 388 String rdnSequence = profile.getRelationRDNSequence(r); 389 if (rdnSequence != null) { 390 return rdnSequence; 391 } 392 } 393 return resource.getString(r.getParentDefinition(), "rdn." + r.getName()); 394 } 395 396 397 398 /** 399 * Removes the last LDAP profile wrapper added using 400 * {@link #pushWrapper(org.opends.server.admin.LDAPProfile.Wrapper)}. 401 * 402 * @throws NoSuchElementException 403 * If there are no LDAP profile wrappers. 404 */ 405 public void popWrapper() throws NoSuchElementException { 406 profiles.removeFirst(); 407 } 408 409 410 411 /** 412 * Decorates the core LDAP profile with the provided LDAP profile 413 * wrapper. All profile requests will be directed to the provided 414 * wrapper before being forwarded onto the core profile if the 415 * request could not be satisfied. 416 * 417 * @param wrapper 418 * The LDAP profile wrapper. 419 */ 420 public void pushWrapper(Wrapper wrapper) { 421 profiles.addFirst(wrapper); 422 } 423}