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