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 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.api;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.HashSet;
033 import java.util.List;
034 import java.util.Set;
035
036 import org.opends.server.admin.std.server.GroupImplementationCfg;
037 import org.opends.server.config.ConfigException;
038 import org.opends.server.types.DirectoryException;
039 import org.opends.server.types.DN;
040 import org.opends.server.types.Entry;
041 import org.opends.server.types.InitializationException;
042 import org.opends.server.types.MemberList;
043 import org.opends.server.types.SearchFilter;
044 import org.opends.server.types.SearchScope;
045
046
047
048 /**
049 * This class defines the set of methods that must be implemented by a
050 * Directory Server group. It is expected that there will be a number
051 * of different types of groups (e.g., legacy static and dynamic
052 * groups, as well as enhanced groups and virtual static groups). The
053 * following operations may be performed on an OpenDS group:
054 * <UL>
055 * <LI>Determining whether a given user is a member of this
056 * group</LI>
057 * <LI>Determining the set of members for this group, optionally
058 * filtered based on some set of criteria.</LI>
059 * <LI>Retrieving or updating the set of nested groups for this
060 * group, if the underlying group type supports nesting).</LI>
061 * <LI>Updating the set of members for this group, if the underlying
062 * group type provides the ability to explicitly add or remove
063 * members.</LI>
064 * </UL>
065 *
066 * @param <T> The type of configuration handled by this group
067 * implementation.
068 */
069 @org.opends.server.types.PublicAPI(
070 stability=org.opends.server.types.StabilityLevel.VOLATILE,
071 mayInstantiate=false,
072 mayExtend=true,
073 mayInvoke=true)
074 public abstract class Group<T extends GroupImplementationCfg>
075 {
076 /**
077 * Initializes a "shell" instance of this group implementation that
078 * may be used to identify and instantiate instances of this type of
079 * group in the directory data.
080 *
081 * @param configuration The configuration for this group
082 * implementation.
083 *
084 * @throws ConfigException If there is a problem with the provided
085 * configuration entry.
086 *
087 * @throws InitializationException If a problem occurs while
088 * attempting to initialize this
089 * group implementation that is
090 * not related to the server
091 * configuration.
092 */
093 public abstract void initializeGroupImplementation(T configuration)
094 throws ConfigException, InitializationException;
095
096
097
098 /**
099 * Indicates whether the provided configuration is acceptable for
100 * this group implementation. It should be possible to call this
101 * method on an uninitialized group implementation instance in order
102 * to determine whether the group implementation would be able to
103 * use the provided configuration.
104 * <BR><BR>
105 * Note that implementations which use a subclass of the provided
106 * configuration class will likely need to cast the configuration
107 * to the appropriate subclass type.
108 *
109 * @param configuration The group implementation
110 * configuration for which to make the
111 * determination.
112 * @param unacceptableReasons A list that may be used to hold the
113 * reasons that the provided
114 * configuration is not acceptable.
115 *
116 * @return {@code true} if the provided configuration is acceptable
117 * for this group implementation, or {@code false} if not.
118 */
119 public boolean isConfigurationAcceptable(
120 GroupImplementationCfg configuration,
121 List<Message> unacceptableReasons)
122 {
123 // This default implementation does not perform any special
124 // validation. It should be overridden by group implementations
125 // that wish to perform more detailed validation.
126 return true;
127 }
128
129
130
131 /**
132 * Performs any necessary finalization that may be needed whenever
133 * this group implementation is taken out of service within the
134 * Directory Server (e.g., if it is disabled or the server is
135 * shutting down).
136 */
137 public void finalizeGroupImplementation()
138 {
139 // No implementation is required by default.
140 }
141
142
143
144 /**
145 * Creates a new group of this type based on the definition
146 * contained in the provided entry. This method must be designed so
147 * that it may be invoked on the "shell" instance created using the
148 * default constructor and initialized with the
149 * {@code initializeGroupImplementation} method.
150 *
151 * @param groupEntry The entry containing the definition for the
152 * group to be created.
153 *
154 * @return The group instance created from the definition in the
155 * provided entry.
156 *
157 * @throws DirectoryException If a problem occurs while trying to
158 * create the group instance.
159 */
160 public abstract Group newInstance(Entry groupEntry)
161 throws DirectoryException;
162
163
164
165 /**
166 * Retrieves a search filter that may be used to identify entries
167 * containing definitions for groups of this type in the Directory
168 * Server. This method must be designed so that it may be invoked
169 * on the "shell" instance created using the default constructor and
170 * initialized with the {@code initializeGroupImplementation}
171 * method.
172 *
173 * @return A search filter that may be used to identify entries
174 * containing definitions for groups of this type in the
175 * Directory Server.
176 *
177 * @throws DirectoryException If a problem occurs while trying to
178 * locate all of the applicable group
179 * definition entries.
180 */
181 public abstract SearchFilter getGroupDefinitionFilter()
182 throws DirectoryException;
183
184
185
186 /**
187 * Indicates whether the provided entry contains a valid definition
188 * for this type of group.
189 *
190 * @param entry The entry for which to make the determination.
191 *
192 * @return {@code true} if the provided entry does contain a valid
193 * definition for this type of group, or {@code false} if
194 * it does not.
195 */
196 public abstract boolean isGroupDefinition(Entry entry);
197
198
199
200 /**
201 * Retrieves the DN of the entry that contains the definition for
202 * this group.
203 *
204 * @return The DN of the entry that contains the definition for
205 * this group.
206 */
207 public abstract DN getGroupDN();
208
209
210
211 /**
212 * Indicates whether this group supports nesting other groups, such
213 * that the members of the nested groups will also be considered
214 * members of this group.
215 *
216 * @return {@code true} if this group supports nesting other
217 * groups, or {@code false} if it does not.
218 */
219 public abstract boolean supportsNestedGroups();
220
221
222
223 /**
224 * Retrieves a list of the DNs of any nested groups whose members
225 * should be considered members of this group.
226 *
227 * @return A list of the DNs of any nested groups whose members
228 * should be considered members of this group.
229 */
230 public abstract List<DN> getNestedGroupDNs();
231
232
233
234 /**
235 * Attempts to add the provided group DN as a nested group within
236 * this group. The change should be committed to persistent storage
237 * through an internal operation.
238 *
239 * @param nestedGroupDN The DN of the group that should be added
240 * to the set of nested groups for this
241 * group.
242 *
243 * @throws UnsupportedOperationException If this group does not
244 * support nesting.
245 *
246 * @throws DirectoryException If a problem occurs while attempting
247 * to nest the provided group DN.
248 */
249 public abstract void addNestedGroup(DN nestedGroupDN)
250 throws UnsupportedOperationException, DirectoryException;
251
252
253
254 /**
255 * Attempts to remove the provided group as a nested group within
256 * this group. The change should be committed to persistent storage
257 * through an internal operation.
258 *
259 * @param nestedGroupDN The DN of the group that should be removed
260 * from the set of nested groups for this
261 * group.
262 *
263 * @throws UnsupportedOperationException If this group does not
264 * support nesting.
265 *
266 * @throws DirectoryException If a problem occurs while attempting
267 * to nest the provided group DN.
268 */
269 public abstract void removeNestedGroup(DN nestedGroupDN)
270 throws UnsupportedOperationException, DirectoryException;
271
272
273
274 /**
275 * Indicates whether the user with the specified DN is a member of
276 * this group. Note that this is a point-in-time determination and
277 * the caller must not cache the result.
278 *
279 * @param userDN The DN of the user for which to make the
280 * determination.
281 *
282 * @return {@code true} if the specified user is currently a member
283 * of this group, or {@code false} if not.
284 *
285 * @throws DirectoryException If a problem occurs while attempting
286 * to make the determination.
287 */
288 public boolean isMember(DN userDN)
289 throws DirectoryException
290 {
291 return isMember(userDN, new HashSet<DN>());
292 }
293
294
295
296 /**
297 * Indicates whether the user with the specified DN is a member of
298 * this group. Note that this is a point-in-time determination and
299 * the caller must not cache the result. Also note that group
300 * implementations that support nesting should use this version of
301 * the method ratehr than the version that does not take a set of
302 * DNs when attempting to determine whether a nested group includes
303 * the target member.
304 *
305 * @param userDN The DN of the user for which to make the
306 * determination.
307 * @param examinedGroups A set of groups that have already been
308 * examined in the process of making the
309 * determination. This provides a mechanism
310 * to prevent infinite recursion due to
311 * circular references (e.g., two groups
312 * include each other as nested groups).
313 * Each time a group instance is checked,
314 * its DN should be added to the list, and
315 * any DN already contained in the list
316 * should be skipped.
317 *
318 * @return {@code true} if the specified user is currently a member
319 * of this group, or {@code false} if not.
320 *
321 * @throws DirectoryException If a problem occurs while attempting
322 * to make the determination.
323 */
324 public abstract boolean isMember(DN userDN, Set<DN> examinedGroups)
325 throws DirectoryException;
326
327
328
329 /**
330 * Indicates whether the user described by the provided user entry
331 * is a member of this group. Note that this is a point-in-time
332 * determination and the caller must not cache the result.
333 *
334 * @param userEntry The entry for the user for which to make the
335 * determination.
336 *
337 * @return {@code true} if the specified user is currently a member
338 * of this group, or {@code false} if not.
339 *
340 * @throws DirectoryException If a problem occurs while attempting
341 * to make the determination.
342 */
343 public boolean isMember(Entry userEntry)
344 throws DirectoryException
345 {
346 return isMember(userEntry, new HashSet<DN>());
347 }
348
349
350
351 /**
352 * Indicates whether the user described by the provided user entry
353 * is a member of this group. Note that this is a point-in-time
354 * determination and the caller must not cache the result. Also
355 * note that group implementations that support nesting should use
356 * this version of the method ratehr than the version that does not
357 * take a set of DNs when attempting to determine whether a nested
358 * group includes the target member.
359 *
360 * @param userEntry The entry for the user for which to make
361 * the determination.
362 * @param examinedGroups A set of groups that have already been
363 * examined in the process of making the
364 * determination. This provides a mechanism
365 * to prevent infinite recursion due to
366 * circular references (e.g., two groups
367 * include each other as nested groups).
368 * Each time a group instance is checked,
369 * its DN should be added to the list, and
370 * any DN already contained in the list
371 * should be skipped.
372 *
373 * @return {@code true} if the specified user is currently a member
374 * of this group, or {@code false} if not.
375 *
376 * @throws DirectoryException If a problem occurs while attempting
377 * to make the determination.
378 */
379 public abstract boolean isMember(Entry userEntry,
380 Set<DN> examinedGroups)
381 throws DirectoryException;
382
383
384
385 /**
386 * Retrieves an iterator that may be used to cursor through the
387 * entries of the members contained in this group. Note that this
388 * is a point-in-time determination, and the caller must not cache
389 * the result. Further, the determination should only include this
390 * group and not members from nested groups.
391 *
392 * @return An iterator that may be used to cursor through the
393 * entries of the members contained in this group.
394 *
395 * @throws DirectoryException If a problem occurs while attempting
396 * to retrieve the set of members.
397 */
398 public MemberList getMembers()
399 throws DirectoryException
400 {
401 return getMembers(null, null, null);
402 }
403
404
405
406 /**
407 * Retrieves an iterator that may be used to cursor through the
408 * entries of the members contained in this group. It may
409 * optionally retrieve a subset of the member entries based on a
410 * given set of criteria. Note that this is a point-in-time
411 * determination, and the caller must not cache the result.
412 *
413 * @param baseDN The base DN that should be used when determining
414 * whether a given entry will be returned. If this
415 * is {@code null}, then all entries will be
416 * considered in the scope of the criteria.
417 * @param scope The scope that should be used when determining
418 * whether a given entry will be returned. It must
419 * not be {@code null} if the provided base DN is
420 * not {@code null}. The scope will be ignored if
421 * no base DN is provided.
422 * @param filter The filter that should be used when determining
423 * whether a given entry will be returned. If this
424 * is {@code null}, then any entry in the scope of
425 * the criteria will be included in the results.
426 *
427 * @return An iterator that may be used to cursor through the
428 * entries of the members contained in this group.
429 *
430 * @throws DirectoryException If a problem occurs while attempting
431 * to retrieve the set of members.
432 */
433 public abstract MemberList getMembers(DN baseDN, SearchScope scope,
434 SearchFilter filter)
435 throws DirectoryException;
436
437
438
439 /**
440 * Indicates whether it is possible to alter the member list for
441 * this group (e.g., in order to add members to the group or remove
442 * members from it).
443 *
444 * @return {@code true} if it is possible to add members to this
445 * group, or {@code false} if not.
446 */
447 public abstract boolean mayAlterMemberList();
448
449
450
451 /**
452 * Attempts to add the provided user as a member of this group. The
453 * change should be committed to persistent storage through an
454 * internal operation.
455 *
456 * @param userEntry The entry for the user to be added as a member
457 * of this group.
458 *
459 * @throws UnsupportedOperationException If this group does not
460 * support altering the
461 * member list.
462 *
463 * @throws DirectoryException If a problem occurs while attempting
464 * to add the provided user as a member
465 * of this group.
466 */
467 public abstract void addMember(Entry userEntry)
468 throws UnsupportedOperationException, DirectoryException;
469
470
471
472 /**
473 * Attempts to remove the specified user as a member of this group.
474 * The change should be committed to persistent storage through an
475 * internal operation.
476 *
477 * @param userDN The DN of the user to remove as a member of this
478 * group.
479 *
480 * @throws UnsupportedOperationException If this group does not
481 * support altering the
482 * member list.
483 *
484 * @throws DirectoryException If a problem occurs while attempting
485 * to remove the provided user as a
486 * member of this group.
487 */
488 public abstract void removeMember(DN userDN)
489 throws UnsupportedOperationException, DirectoryException;
490
491
492
493 /**
494 * Retrieves a string representation of this group.
495 *
496 * @return A string representation of this group.
497 */
498 public String toString()
499 {
500 StringBuilder buffer = new StringBuilder();
501 toString(buffer);
502 return buffer.toString();
503 }
504
505
506
507 /**
508 * Appends a string representation of this group to the provided
509 * buffer.
510 *
511 * @param buffer The buffer to which the string representation
512 * should be appended.
513 */
514 public abstract void toString(StringBuilder buffer);
515 }
516