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
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2008 Sun Microsystems, Inc.
026 */
027
028 package org.opends.server.admin;
029
030
031
032 import java.util.Arrays;
033 import java.util.HashSet;
034 import java.util.LinkedList;
035 import java.util.List;
036 import java.util.MissingResourceException;
037 import java.util.NoSuchElementException;
038 import 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 */
051 public 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 getInstantiableRelationChildRDNType(
108 InstantiableRelationDefinition<?, ?> r) {
109 return null;
110 }
111
112
113
114 /**
115 * Get the principle object class associated with the specified
116 * definition.
117 * <p>
118 * The default implementation of this method is to return
119 * <code>null</code>.
120 *
121 * @param d
122 * The managed object definition.
123 * @return Returns the principle object class associated with the
124 * specified definition, or <code>null</code> if the
125 * managed object definition is not handled by this LDAP
126 * profile wrapper.
127 */
128 public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d) {
129 return null;
130 }
131
132
133
134 /**
135 * Get an LDAP RDN sequence associatied with a relation.
136 * <p>
137 * The default implementation of this method is to return
138 * <code>null</code>.
139 *
140 * @param r
141 * The relation.
142 * @return Returns the LDAP RDN sequence associatied with a
143 * relation, or <code>null</code> if the relation is not
144 * handled by this LDAP profile wrapper.
145 */
146 public String getRelationRDNSequence(RelationDefinition<?, ?> r) {
147 return null;
148 }
149 }
150
151 // The singleton instance.
152 private static final LDAPProfile INSTANCE = new LDAPProfile();
153
154
155
156 /**
157 * Get the global LDAP profile instance.
158 *
159 * @return Returns the global LDAP profile instance.
160 */
161 public static LDAPProfile getInstance() {
162 return INSTANCE;
163 }
164
165 // The list of profile wrappers.
166 private final LinkedList<Wrapper> profiles = new LinkedList<Wrapper>();;
167
168 // The LDAP profile property table.
169 private final ManagedObjectDefinitionResource resource =
170 ManagedObjectDefinitionResource.createForProfile("ldap");
171
172
173
174 // Prevent construction.
175 private LDAPProfile() {
176 // No implementation required.
177 }
178
179
180
181 /**
182 * Get the name of the LDAP attribute associated with the specified
183 * property definition.
184 *
185 * @param d
186 * The managed object definition.
187 * @param pd
188 * The property definition.
189 * @return Returns the name of the LDAP attribute associated with
190 * the specified property definition.
191 * @throws MissingResourceException
192 * If the LDAP profile properties file associated with the
193 * provided managed object definition could not be loaded.
194 */
195 public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
196 PropertyDefinition<?> pd) throws MissingResourceException {
197 for (Wrapper profile : profiles) {
198 String attributeName = profile.getAttributeName(d, pd);
199 if (attributeName != null) {
200 return attributeName;
201 }
202 }
203 return resource.getString(d, "attribute." + pd.getName());
204 }
205
206
207
208 /**
209 * Gets the LDAP RDN attribute type for child entries of an
210 * instantiable relation.
211 *
212 * @param r
213 * The instantiable relation.
214 * @return Returns the LDAP RDN attribute type for child entries of
215 * an instantiable relation.
216 * @throws MissingResourceException
217 * If the LDAP profile properties file associated with the
218 * provided managed object definition could not be loaded.
219 */
220 public String getInstantiableRelationChildRDNType(
221 InstantiableRelationDefinition<?, ?> r) throws MissingResourceException {
222 if (r.getNamingPropertyDefinition() != null) {
223 // Use the attribute associated with the naming property.
224 return getAttributeName(r.getChildDefinition(), r
225 .getNamingPropertyDefinition());
226 } else {
227 for (Wrapper profile : profiles) {
228 String rdnType = profile.getInstantiableRelationChildRDNType(r);
229 if (rdnType != null) {
230 return rdnType;
231 }
232 }
233 return resource.getString(r.getParentDefinition(), "naming-attribute."
234 + r.getName());
235 }
236 }
237
238
239
240 /**
241 * Gets the LDAP object classes associated with an instantiable
242 * relation branch. The branch is the parent entry of child managed
243 * objects.
244 *
245 * @param r
246 * The instantiable relation.
247 * @return Returns the LDAP object classes associated with an
248 * instantiable relation branch.
249 */
250 public List<String> getInstantiableRelationObjectClasses(
251 InstantiableRelationDefinition<?, ?> r) {
252 return Arrays.asList(new String[] { "top", "ds-cfg-branch" });
253 }
254
255
256
257 /**
258 * Get the principle object class associated with the specified
259 * definition.
260 *
261 * @param d
262 * The managed object definition.
263 * @return Returns the principle object class associated with the
264 * specified definition.
265 * @throws MissingResourceException
266 * If the LDAP profile properties file associated with the
267 * provided managed object definition could not be loaded.
268 */
269 public String getObjectClass(AbstractManagedObjectDefinition<?, ?> d)
270 throws MissingResourceException {
271 if (d.isTop()) {
272 return "top";
273 }
274
275 for (Wrapper profile : profiles) {
276 String objectClass = profile.getObjectClass(d);
277 if (objectClass != null) {
278 return objectClass;
279 }
280 }
281 return resource.getString(d, "objectclass");
282 }
283
284
285
286 /**
287 * Get all the object classes associated with the specified
288 * definition.
289 * <p>
290 * The returned list is ordered such that the uppermost object
291 * classes appear first (e.g. top).
292 *
293 * @param d
294 * The managed object definition.
295 * @return Returns all the object classes associated with the
296 * specified definition.
297 * @throws MissingResourceException
298 * If the LDAP profile properties file associated with the
299 * provided managed object definition could not be loaded.
300 */
301 public List<String> getObjectClasses(AbstractManagedObjectDefinition<?, ?> d)
302 throws MissingResourceException {
303 LinkedList<String> objectClasses = new LinkedList<String>();
304 Set<String> s = new HashSet<String>();
305
306 // Add the object classes from the parent hierarchy.
307 while (d != null) {
308 String oc = getObjectClass(d);
309 if (!s.contains(oc)) {
310 objectClasses.addFirst(oc);
311 s.add(oc);
312 }
313 d = d.getParent();
314 }
315
316 if (!s.contains("top")) {
317 objectClasses.addFirst("top");
318 }
319
320 return objectClasses;
321 }
322
323
324
325 /**
326 * Get an LDAP RDN sequence associatied with a relation.
327 *
328 * @param r
329 * The relation.
330 * @return Returns the LDAP RDN sequence associatied with a
331 * relation.
332 * @throws MissingResourceException
333 * If the LDAP profile properties file associated with the
334 * provided managed object definition could not be loaded.
335 */
336 public String getRelationRDNSequence(RelationDefinition<?, ?> r)
337 throws MissingResourceException {
338 for (Wrapper profile : profiles) {
339 String rdnSequence = profile.getRelationRDNSequence(r);
340 if (rdnSequence != null) {
341 return rdnSequence;
342 }
343 }
344 return resource.getString(r.getParentDefinition(), "rdn." + r.getName());
345 }
346
347
348
349 /**
350 * Removes the last LDAP profile wrapper added using
351 * {@link #pushWrapper(org.opends.server.admin.LDAPProfile.Wrapper)}.
352 *
353 * @throws NoSuchElementException
354 * If there are no LDAP profile wrappers.
355 */
356 public void popWrapper() throws NoSuchElementException {
357 profiles.removeFirst();
358 }
359
360
361
362 /**
363 * Decorates the core LDAP profile with the provided LDAP profile
364 * wrapper. All profile requests will be directed to the provided
365 * wrapper before being forwarded onto the core profile if the
366 * request could not be satisfied.
367 *
368 * @param wrapper
369 * The LDAP profile wrapper.
370 */
371 public void pushWrapper(Wrapper wrapper) {
372 profiles.addFirst(wrapper);
373 }
374 }