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