/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2012 ForgeRock AS
*/
package org.opends.server.api;
import org.opends.messages.Message;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.opends.server.admin.std.server.GroupImplementationCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.MemberList;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
/**
* This class defines the set of methods that must be implemented by a
* Directory Server group. It is expected that there will be a number
* of different types of groups (e.g., legacy static and dynamic
* groups, as well as enhanced groups and virtual static groups). The
* following operations may be performed on an OpenDS group:
* <UL>
* <LI>Determining whether a given user is a member of this
* group</LI>
* <LI>Determining the set of members for this group, optionally
* filtered based on some set of criteria.</LI>
* <LI>Retrieving or updating the set of nested groups for this
* group, if the underlying group type supports nesting).</LI>
* <LI>Updating the set of members for this group, if the underlying
* group type provides the ability to explicitly add or remove
* members.</LI>
* </UL>
*
* @param <T> The type of configuration handled by this group
* implementation.
*/
@org.opends.server.types.PublicAPI(
stability=org.opends.server.types.StabilityLevel.VOLATILE,
mayInstantiate=false,
mayExtend=true,
mayInvoke=true)
public abstract class Group<T extends GroupImplementationCfg>
{
/**
* Initializes a "shell" instance of this group implementation that
* may be used to identify and instantiate instances of this type of
* group in the directory data.
*
* @param configuration The configuration for this group
* implementation.
*
* @throws ConfigException If there is a problem with the provided
* configuration entry.
*
* @throws InitializationException If a problem occurs while
* attempting to initialize this
* group implementation that is
* not related to the server
* configuration.
*/
public abstract void initializeGroupImplementation(T configuration)
throws ConfigException, InitializationException;
/**
* Indicates whether the provided configuration is acceptable for
* this group implementation. It should be possible to call this
* method on an uninitialized group implementation instance in order
* to determine whether the group implementation would be able to
* use the provided configuration.
* <BR><BR>
* Note that implementations which use a subclass of the provided
* configuration class will likely need to cast the configuration
* to the appropriate subclass type.
*
* @param configuration The group implementation
* configuration for which to make the
* determination.
* @param unacceptableReasons A list that may be used to hold the
* reasons that the provided
* configuration is not acceptable.
*
* @return {@code true} if the provided configuration is acceptable
* for this group implementation, or {@code false} if not.
*/
public boolean isConfigurationAcceptable(
GroupImplementationCfg configuration,
List<Message> unacceptableReasons)
{
// This default implementation does not perform any special
// validation. It should be overridden by group implementations
// that wish to perform more detailed validation.
return true;
}
/**
* Performs any necessary finalization that may be needed whenever
* this group implementation is taken out of service within the
* Directory Server (e.g., if it is disabled or the server is
* shutting down).
*/
public void finalizeGroupImplementation()
{
// No implementation is required by default.
}
/**
* Creates a new group of this type based on the definition
* contained in the provided entry. This method must be designed so
* that it may be invoked on the "shell" instance created using the
* default constructor and initialized with the
* {@code initializeGroupImplementation} method.
*
* @param groupEntry The entry containing the definition for the
* group to be created.
*
* @return The group instance created from the definition in the
* provided entry.
*
* @throws DirectoryException If a problem occurs while trying to
* create the group instance.
*/
public abstract Group newInstance(Entry groupEntry)
throws DirectoryException;
/**
* Retrieves a search filter that may be used to identify entries
* containing definitions for groups of this type in the Directory
* Server. This method must be designed so that it may be invoked
* on the "shell" instance created using the default constructor and
* initialized with the {@code initializeGroupImplementation}
* method.
*
* @return A search filter that may be used to identify entries
* containing definitions for groups of this type in the
* Directory Server.
*
* @throws DirectoryException If a problem occurs while trying to
* locate all of the applicable group
* definition entries.
*/
public abstract SearchFilter getGroupDefinitionFilter()
throws DirectoryException;
/**
* Indicates whether the provided entry contains a valid definition
* for this type of group.
*
* @param entry The entry for which to make the determination.
*
* @return {@code true} if the provided entry does contain a valid
* definition for this type of group, or {@code false} if
* it does not.
*/
public abstract boolean isGroupDefinition(Entry entry);
/**
* Retrieves the DN of the entry that contains the definition for
* this group.
*
* @return The DN of the entry that contains the definition for
* this group.
*/
public abstract DN getGroupDN();
/**
* Sets the DN of the entry that contains the definition for
* this group.
*
* @param groupDN The DN of the entry that contains the
* definition for this group.
*/
public abstract void setGroupDN(DN groupDN);
/**
* Indicates whether this group supports nesting other groups, such
* that the members of the nested groups will also be considered
* members of this group.
*
* @return {@code true} if this group supports nesting other
* groups, or {@code false} if it does not.
*/
public abstract boolean supportsNestedGroups();
/**
* Retrieves a list of the DNs of any nested groups whose members
* should be considered members of this group.
*
* @return A list of the DNs of any nested groups whose members
* should be considered members of this group.
*/
public abstract List<DN> getNestedGroupDNs();
/**
* Attempts to add the provided group DN as a nested group within
* this group. The change should be committed to persistent storage
* through an internal operation.
*
* @param nestedGroupDN The DN of the group that should be added
* to the set of nested groups for this
* group.
*
* @throws UnsupportedOperationException If this group does not
* support nesting.
*
* @throws DirectoryException If a problem occurs while attempting
* to nest the provided group DN.
*/
public abstract void addNestedGroup(DN nestedGroupDN)
throws UnsupportedOperationException, DirectoryException;
/**
* Attempts to remove the provided group as a nested group within
* this group. The change should be committed to persistent storage
* through an internal operation.
*
* @param nestedGroupDN The DN of the group that should be removed
* from the set of nested groups for this
* group.
*
* @throws UnsupportedOperationException If this group does not
* support nesting.
*
* @throws DirectoryException If a problem occurs while attempting
* to nest the provided group DN.
*/
public abstract void removeNestedGroup(DN nestedGroupDN)
throws UnsupportedOperationException, DirectoryException;
/**
* Indicates whether the user with the specified DN is a member of
* this group. Note that this is a point-in-time determination and
* the caller must not cache the result.
*
* @param userDN The DN of the user for which to make the
* determination.
*
* @return {@code true} if the specified user is currently a member
* of this group, or {@code false} if not.
*
* @throws DirectoryException If a problem occurs while attempting
* to make the determination.
*/
public boolean isMember(DN userDN)
throws DirectoryException
{
if (userDN != null)
return isMember(userDN, new HashSet<DN>());
return false;
}
/**
* Indicates whether the user with the specified DN is a member of
* this group. Note that this is a point-in-time determination and
* the caller must not cache the result. Also note that group
* implementations that support nesting should use this version of
* the method rather than the version that does not take a set of
* DNs when attempting to determine whether a nested group includes
* the target member.
*
* @param userDN The DN of the user for which to make the
* determination.
* @param examinedGroups A set of groups that have already been
* examined in the process of making the
* determination. This provides a mechanism
* to prevent infinite recursion due to
* circular references (e.g., two groups
* include each other as nested groups).
* Each time a group instance is checked,
* its DN should be added to the list, and
* any DN already contained in the list
* should be skipped.
*
* @return {@code true} if the specified user is currently a member
* of this group, or {@code false} if not.
*
* @throws DirectoryException If a problem occurs while attempting
* to make the determination.
*/
public abstract boolean isMember(DN userDN, Set<DN> examinedGroups)
throws DirectoryException;
/**
* Indicates whether the user described by the provided user entry
* is a member of this group. Note that this is a point-in-time
* determination and the caller must not cache the result.
*
* @param userEntry The entry for the user for which to make the
* determination.
*
* @return {@code true} if the specified user is currently a member
* of this group, or {@code false} if not.
*
* @throws DirectoryException If a problem occurs while attempting
* to make the determination.
*/
public boolean isMember(Entry userEntry)
throws DirectoryException
{
return isMember(userEntry, new HashSet<DN>());
}
/**
* Indicates whether the user described by the provided user entry
* is a member of this group. Note that this is a point-in-time
* determination and the caller must not cache the result. Also
* note that group implementations that support nesting should use
* this version of the method rather than the version that does not
* take a set of DNs when attempting to determine whether a nested
* group includes the target member.
*
* @param userEntry The entry for the user for which to make
* the determination.
* @param examinedGroups A set of groups that have already been
* examined in the process of making the
* determination. This provides a mechanism
* to prevent infinite recursion due to
* circular references (e.g., two groups
* include each other as nested groups).
* Each time a group instance is checked,
* its DN should be added to the list, and
* any DN already contained in the list
* should be skipped.
*
* @return {@code true} if the specified user is currently a member
* of this group, or {@code false} if not.
*
* @throws DirectoryException If a problem occurs while attempting
* to make the determination.
*/
public abstract boolean isMember(Entry userEntry,
Set<DN> examinedGroups)
throws DirectoryException;
/**
* Retrieves an iterator that may be used to cursor through the
* entries of the members contained in this group. Note that this
* is a point-in-time determination, and the caller must not cache
* the result. Further, the determination should only include this
* group and not members from nested groups.
*
* @return An iterator that may be used to cursor through the
* entries of the members contained in this group.
*
* @throws DirectoryException If a problem occurs while attempting
* to retrieve the set of members.
*/
public MemberList getMembers()
throws DirectoryException
{
return getMembers(null, null, null);
}
/**
* Retrieves an iterator that may be used to cursor through the
* entries of the members contained in this group. It may
* optionally retrieve a subset of the member entries based on a
* given set of criteria. Note that this is a point-in-time
* determination, and the caller must not cache the result.
*
* @param baseDN The base DN that should be used when determining
* whether a given entry will be returned. If this
* is {@code null}, then all entries will be
* considered in the scope of the criteria.
* @param scope The scope that should be used when determining
* whether a given entry will be returned. It must
* not be {@code null} if the provided base DN is
* not {@code null}. The scope will be ignored if
* no base DN is provided.
* @param filter The filter that should be used when determining
* whether a given entry will be returned. If this
* is {@code null}, then any entry in the scope of
* the criteria will be included in the results.
*
* @return An iterator that may be used to cursor through the
* entries of the members contained in this group.
*
* @throws DirectoryException If a problem occurs while attempting
* to retrieve the set of members.
*/
public abstract MemberList getMembers(DN baseDN, SearchScope scope,
SearchFilter filter)
throws DirectoryException;
/**
* Indicates whether it is possible to alter the member list for
* this group (e.g., in order to add members to the group or remove
* members from it).
*
* @return {@code true} if it is possible to add members to this
* group, or {@code false} if not.
*/
public abstract boolean mayAlterMemberList();
/**
* Attempts to add the provided user as a member of this group. The
* change should be committed to persistent storage through an
* internal operation.
*
* @param userEntry The entry for the user to be added as a member
* of this group.
*
* @throws UnsupportedOperationException If this group does not
* support altering the
* member list.
*
* @throws DirectoryException If a problem occurs while attempting
* to add the provided user as a member
* of this group.
*/
public abstract void addMember(Entry userEntry)
throws UnsupportedOperationException, DirectoryException;
/**
* Attempts to remove the specified user as a member of this group.
* The change should be committed to persistent storage through an
* internal operation.
*
* @param userDN The DN of the user to remove as a member of this
* group.
*
* @throws UnsupportedOperationException If this group does not
* support altering the
* member list.
*
* @throws DirectoryException If a problem occurs while attempting
* to remove the provided user as a
* member of this group.
*/
public abstract void removeMember(DN userDN)
throws UnsupportedOperationException, DirectoryException;
/**
* Retrieves a string representation of this group.
*
* @return A string representation of this group.
*/
public String toString()
{
StringBuilder buffer = new StringBuilder();
toString(buffer);
return buffer.toString();
}
/**
* Appends a string representation of this group to the provided
* buffer.
*
* @param buffer The buffer to which the string representation
* should be appended.
*/
public abstract void toString(StringBuilder buffer);
}