GroupManager.java revision a84551d9d7d05a9b2c8e087dcba3839e8ce7504e
/*
* 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
* 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
*
*
* Portions Copyright 2007 Sun Microsystems, Inc.
*/
/**
* This class provides a mechanism for interacting with all groups defined in
* the Directory Server. It will handle all necessary processing at server
* startup to identify and load all group implementations, as well as to find
* all group instances within the server.
* <BR><BR>
* FIXME: At the present time, it assumes that all of the necessary
* information about all of the groups defined in the server can be held in
* memory. If it is determined that this approach is not workable in all cases,
* then we will need an alternate strategy.
*/
public class GroupManager
{
/**
* The tracer object for the debug logger.
*/
// A mapping between the DNs of the config entries and the associated
// group implementations.
// A mapping between the DNs of all group entries and the corresponding
// group instances.
// The configuration handler for the Directory Server.
private ConfigHandler configHandler;
/**
* Creates a new instance of this group manager.
*/
public GroupManager()
{
}
/**
* Initializes all group implementations currently defined in the Directory
* Server configuration. This should only be called at Directory Server
* startup.
*
* @throws ConfigException If a configuration problem causes the group
* implementation initialization process to fail.
*
* @throws InitializationException If a problem occurs while initializing
* the group implementations that is not
* related to the server configuration.
*/
public void initializeGroupImplementations()
{
// First, get the configuration base entry.
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
{
// The group implementation base entry does not exist. This is not
// acceptable, so throw an exception.
}
// Register add and delete listeners with the group implementation base
// entry. We don't care about modifications to it.
baseEntry.registerAddListener(this);
baseEntry.registerDeleteListener(this);
// See if the base entry has any children. If not, then we don't need to do
// anything else.
if (! baseEntry.hasChildren())
{
return;
}
// Iterate through the child entries and process them as group
// implementation configuration entries.
{
childEntry.registerChangeListener(this);
{
continue;
}
try
{
{
{
}
else
{
{
}
}
}
}
catch (Exception e)
{
}
}
}
/**
* Performs any cleanup work that may be needed when the server is shutting
* down.
*/
public void finalizeGroupManager()
{
{
}
}
/**
* Retrieves an {@code Iterable} object that may be used to cursor across the
* group implementations defined in the server.
*
* @return An {@code Iterable} object that may be used to cursor across the
* group implementations defined in the server.
*/
{
return groupImplementations.values();
}
/**
* Retrieves an {@code Iterable} object that may be used to cursor across the
* group instances defined in the server.
*
* @return An {@code Iterable} object that may be used to cursor across the
* group instances defined in the server.
*/
{
return groupInstances.values();
}
/**
* Retrieves the group instance defined in the entry with the specified DN.
*
* @param entryDN The DN of the entry containing the definition of the group
* instance to retrieve.
*
* @return The group instance defined in the entry with the specified DN, or
* {@code null} if no such group is currently defined.
*/
{
{
// FIXME -- Should we try to retrieve the corresponding entry and see if
// it is a group?
}
return group;
}
/**
* Indicates whether the configuration entry that will result from a proposed
* modification is acceptable to this change listener.
*
* @param configEntry The configuration entry that will result from
* the requested update.
* @param unacceptableReason A buffer to which this method can append a
* human-readable message explaining why the
* proposed change is not acceptable.
*
* @return <CODE>true</CODE> if the proposed entry contains an acceptable
* configuration, or <CODE>false</CODE> if it does not.
*/
{
// Make sure that the entry has an appropriate objectclass for an extended
// operation handler.
{
return false;
}
// Make sure that the entry specifies the group implementation class name.
try
{
true, false, true);
if (classNameAttr == null)
{
return false;
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
try
{
}
catch(Exception e)
{
if (debugEnabled())
{
}
return false;
}
// See if this extended operation handler should be enabled.
try
{
false);
if (enabledAttr == null)
{
return false;
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
// If we've gotten here then the group implementation entry appears to be
// acceptable.
return true;
}
/**
* Attempts to apply a new configuration to this Directory Server component
* based on the provided changed entry.
*
* @param configEntry The configuration entry that containing the updated
* configuration for this component.
*
* @return Information about the result of processing the configuration
* change.
*/
{
boolean adminActionRequired = false;
// Make sure that the entry has an appropriate objectclass for a group
// implementation.
{
}
// Get the corresponding group implementation instance if it is active.
// See if this handler should be enabled or disabled.
boolean needsEnabled = false;
try
{
if (enabledAttr == null)
{
messages);
}
if (enabledAttr.activeValue())
{
if (groupImplementation == null)
{
needsEnabled = true;
}
else
{
// The group implementation is already active, so no action is
// required.
}
}
else
{
if (groupImplementation == null)
{
// The group implementation is already disabled, so no action is
// required and we can short-circuit out of this processing.
messages);
}
else
{
// The group implementation is active, so it needs to be disabled. Do
// this and return that we were successful.
{
{
}
}
messages);
}
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
// Make sure that the entry specifies the group implementation class name.
// If it has changed, then we will not try to dynamically apply it.
try
{
true, false, true);
if (classNameAttr == null)
{
messages);
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
boolean classChanged = false;
if (groupImplementation != null)
{
}
if (classChanged)
{
// This will not be applied dynamically. Add a message to the response
// and indicate that admin action is required.
adminActionRequired = true;
}
if (needsEnabled)
{
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
messages);
}
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
messages);
}
// FIXME -- We need to make sure to find all groups of this type in the
// server before returning.
}
// If we've gotten here, then there haven't been any changes to anything
// that we care about.
}
/**
* Indicates whether the configuration entry that will result from a proposed
* add is acceptable to this add listener.
*
* @param configEntry The configuration entry that will result from
* the requested add.
* @param unacceptableReason A buffer to which this method can append a
* human-readable message explaining why the
* proposed entry is not acceptable.
*
* @return <CODE>true</CODE> if the proposed entry contains an acceptable
* configuration, or <CODE>false</CODE> if it does not.
*/
{
// Make sure that no entry already exists with the specified DN.
{
int msgID = MSGID_CONFIG_GROUP_EXISTS;
return false;
}
// Make sure that the entry has an appropriate objectclass for a group
// implementation.
{
return false;
}
// Make sure that the entry specifies the group implementation class.
try
{
true, false, true);
if (classNameAttr == null)
{
return false;
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
// If the handler is a configurable component, then make sure that its
// configuration is valid.
if (groupImplementation instanceof ConfigurableComponent)
{
{
if (errorMessages.isEmpty())
{
}
else
{
{
}
}
return false;
}
}
// See if this handler should be enabled.
try
{
false);
if (enabledAttr == null)
{
return false;
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
return false;
}
// If we've gotten here then the handler entry appears to be acceptable.
return true;
}
/**
* Attempts to apply a new configuration based on the provided added entry.
*
* @param configEntry The new configuration entry that contains the
* configuration to apply.
*
* @return Information about the result of processing the configuration
* change.
*/
{
boolean adminActionRequired = false;
// Make sure that the entry has an appropriate objectclass for a group
// implementation.
{
}
// See if this group implementation should be enabled or disabled.
try
{
false);
if (enabledAttr == null)
{
// The attribute doesn't exist, so it will be disabled by default.
messages);
}
else if (! enabledAttr.activeValue())
{
// It is explicitly configured as disabled, so we don't need to do
// anything.
messages);
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
// Make sure that the entry specifies the group implementation class name.
try
{
true, false, true);
if (classNameAttr == null)
{
messages);
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
// Load and initialize the group implementation class, and register it with
// the Directory Server.
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
}
}
/**
* Indicates whether it is acceptable to remove the provided configuration
* entry.
*
* @param configEntry The configuration entry that will be removed
* from the configuration.
* @param unacceptableReason A buffer to which this method can append a
* human-readable message explaining why the
* proposed delete is not acceptable.
*
* @return <CODE>true</CODE> if the proposed entry may be removed from the
* configuration, or <CODE>false</CODE> if not.
*/
{
// A delete should always be acceptable, so just return true.
return true;
}
/**
* Attempts to apply a new configuration based on the provided deleted entry.
*
* @param configEntry The new configuration entry that has been deleted.
*
* @return Information about the result of processing the configuration
* change.
*/
{
boolean adminActionRequired = false;
// See if the entry is registered as a group implementation. If so, then
// deregister it and remove any groups of that type.
if (groupImplementation != null)
{
{
{
}
}
}
}
/**
* {@inheritDoc} In this case, the server will search the backend to find
* all group instances that it may contain and register them with this group
* manager.
*/
{
{
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
// FIXME -- Is there anything that we need to do here?
continue;
}
{
try
{
{
continue;
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
// FIXME -- Is there anything that we need to do here?
continue;
}
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
// FIXME -- Is there anything that we need to do here?
continue;
}
{
try
{
}
catch (Exception e)
{
if (debugEnabled())
{
}
// FIXME -- Handle this.
continue;
}
}
}
}
}
/**
* {@inheritDoc} In this case, the server will de-register all group
* instances associated with entries in the provided backend.
*/
{
{
{
}
}
}
/**
* {@inheritDoc} In this case, each entry is checked to see if it contains
* a group definition, and if so it will be instantiated and registered with
* this group manager.
*/
{
if (requestControls != null)
{
for (Control c : requestControls)
{
{
return;
}
}
}
}
/**
* {@inheritDoc} In this case, if the entry is associated with a registered
* group instance, then that group instance will be deregistered.
*/
{
if (requestControls != null)
{
for (Control c : requestControls)
{
{
return;
}
}
}
}
/**
* {@inheritDoc} In this case, if the entry is associated with a registered
* group instance, then that instance will be recreated from the contents of
* the provided entry and re-registered with the group manager.
*/
{
if (requestControls != null)
{
for (Control c : requestControls)
{
{
return;
}
}
}
{
synchronized (groupInstances)
{
{
// This should never happen, but check for it anyway.
}
}
}
}
/**
* {@inheritDoc} In this case, if the entry is associated with a registered
* group instance, then that instance will be recreated from the contents of
* the provided entry and re-registered with the group manager under the new
* DN, and the old instance will be deregistered.
*/
public void handleModifyDNOperation(
{
if (requestControls != null)
{
for (Control c : requestControls)
{
{
return;
}
}
}
{
synchronized (groupInstances)
{
}
}
}
/**
* Attempts to create a group instance from the provided entry, and if that is
* successful then register it with the server, overwriting any existing
* group instance that may be registered with the same DN.
*
* @param entry The entry containing the potential group definition.
*/
{
{
try
{
{
}
}
catch (Exception e)
{
if (debugEnabled())
{
}
// FIXME -- Do we need to do anything else?
}
}
}
/**
* Removes all group instances that might happen to be registered with the
* group manager. This method is only intended for testing purposes and
* should not be called by any other code.
*/
void deregisterAllGroups()
{
}
}