| | |
| | | public boolean isUsable(ServerManagedObject<?> managedObject, Collection<LocalizableMessage> unacceptableReasons) |
| | | throws ConfigException { |
| | | SortedSet<String> names = managedObject.getPropertyValues(AggregationPropertyDefinition.this); |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | ServerManagementContext context = managedObject.getServerContext(); |
| | | LocalizableMessage thisUFN = managedObject.getManagedObjectDefinition().getUserFriendlyName(); |
| | | String thisDN = managedObject.getDN().toString(); |
| | | LocalizableMessage thatUFN = getRelationDefinition().getUserFriendlyName(); |
| | |
| | | |
| | | // Delete listeners need to be registered against the parent |
| | | // entry of the referenced components. |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | ServerManagementContext context = managedObject.getServerContext(); |
| | | ManagedObjectPath<?, ?> parentPath = getParentPath(); |
| | | ServerManagedObject<?> parent = context.getManagedObject(parentPath); |
| | | |
| | |
| | | @Override |
| | | public void performPostDelete(ServerManagedObject<?> managedObject) throws ConfigException { |
| | | // Remove any registered delete and change listeners. |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | ServerManagementContext context = managedObject.getServerContext(); |
| | | DN dn = managedObject.getDN(); |
| | | |
| | | // Delete listeners need to be deregistered against the parent |
| | |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | |
| | | |
| | | import java.util.Collection; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Common features of config listener adaptors. |
| | | */ |
| | | abstract class AbstractConfigListenerAdaptor { |
| | | |
| | | /** |
| | | * Create a new config listener adaptor. |
| | | */ |
| | | protected AbstractConfigListenerAdaptor() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Concatenate a list of messages into a single message. |
| | | * |
| | | * @param reasons |
| | | * The list of messages to concatenate. |
| | | * @param unacceptableReason |
| | | * The single message to which messages should be appended. |
| | | */ |
| | | protected final void generateUnacceptableReason(Collection<LocalizableMessage> reasons, |
| | | LocalizableMessageBuilder unacceptableReason) { |
| | | boolean isFirst = true; |
| | | for (LocalizableMessage reason : reasons) { |
| | | if (isFirst) { |
| | | isFirst = false; |
| | | } else { |
| | | unacceptableReason.append(" "); |
| | | } |
| | | unacceptableReason.append(reason); |
| | | /** |
| | | * Create a new config listener adaptor. |
| | | */ |
| | | protected AbstractConfigListenerAdaptor() { |
| | | // No implementation required. |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Concatenate a list of messages into a single message. |
| | | * |
| | | * @param reasons |
| | | * The list of messages to concatenate. |
| | | * @param unacceptableReason |
| | | * The single message to which messages should be appended. |
| | | */ |
| | | protected final void generateUnacceptableReason(Collection<LocalizableMessage> reasons, |
| | | LocalizableMessageBuilder unacceptableReason) { |
| | | boolean isFirst = true; |
| | | for (LocalizableMessage reason : reasons) { |
| | | if (isFirst) { |
| | | isFirst = false; |
| | | } else { |
| | | unacceptableReason.append(" "); |
| | | } |
| | | unacceptableReason.append(reason); |
| | | } |
| | | } |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | |
| | | |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | |
| | | import org.opends.server.admin.SetRelationDefinition; |
| | | import org.opends.server.admin.DefinitionDecodingException.Reason; |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | |
| | | |
| | | |
| | | /** |
| | | * An adaptor class which converts {@link ConfigAddListener} callbacks |
| | | * to {@link ServerManagedObjectAddListener} callbacks. |
| | | * An adaptor class which converts {@link ConfigAddListener} callbacks to |
| | | * {@link ServerManagedObjectAddListener} callbacks. |
| | | * |
| | | * @param <S> |
| | | * The type of server configuration handled by the add |
| | | * listener. |
| | | * The type of server configuration handled by the add listener. |
| | | */ |
| | | final class ConfigAddListenerAdaptor<S extends Configuration> extends |
| | | AbstractConfigListenerAdaptor implements ConfigAddListener { |
| | | final class ConfigAddListenerAdaptor<S extends Configuration> extends AbstractConfigListenerAdaptor implements |
| | | ConfigAddListener { |
| | | |
| | | private static final Logger debugLogger = LoggerFactory.getLogger(ConfigAddListenerAdaptor.class); |
| | | private static final Logger debugLogger = LoggerFactory.getLogger(ConfigAddListenerAdaptor.class); |
| | | |
| | | // Cached managed object between accept/apply callbacks. |
| | | private ServerManagedObject<? extends S> cachedManagedObject; |
| | | // Cached managed object between accept/apply callbacks. |
| | | private ServerManagedObject<? extends S> cachedManagedObject; |
| | | |
| | | // The instantiable relation. |
| | | private final InstantiableRelationDefinition<?, S> instantiableRelation; |
| | | // The instantiable relation. |
| | | private final InstantiableRelationDefinition<?, S> instantiableRelation; |
| | | |
| | | // The set relation. |
| | | private final SetRelationDefinition<?, S> setRelation; |
| | | // The set relation. |
| | | private final SetRelationDefinition<?, S> setRelation; |
| | | |
| | | // The underlying add listener. |
| | | private final ServerManagedObjectAddListener<S> listener; |
| | | // The underlying add listener. |
| | | private final ServerManagedObjectAddListener<S> listener; |
| | | |
| | | // The optional relation. |
| | | private final OptionalRelationDefinition<?, S> optionalRelation; |
| | | // The optional relation. |
| | | private final OptionalRelationDefinition<?, S> optionalRelation; |
| | | |
| | | // The managed object path of the parent. |
| | | private final ManagedObjectPath<?, ?> path; |
| | | // The managed object path of the parent. |
| | | private final ManagedObjectPath<?, ?> path; |
| | | |
| | | private final ServerManagementContext serverContext; |
| | | |
| | | |
| | | /** |
| | | * Create a new configuration add listener adaptor for an |
| | | * instantiable relation. |
| | | * |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | | * The instantiable relation. |
| | | * @param listener |
| | | * The underlying add listener. |
| | | */ |
| | | public ConfigAddListenerAdaptor(ManagedObjectPath<?, ?> path, |
| | | InstantiableRelationDefinition<?, S> relation, |
| | | ServerManagedObjectAddListener<S> listener) { |
| | | this.path = path; |
| | | this.instantiableRelation = relation; |
| | | this.optionalRelation = null; |
| | | this.setRelation = null; |
| | | this.listener = listener; |
| | | this.cachedManagedObject = null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create a new configuration add listener adaptor for an optional |
| | | * relation. |
| | | * |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | | * The optional relation. |
| | | * @param listener |
| | | * The underlying add listener. |
| | | */ |
| | | public ConfigAddListenerAdaptor(ManagedObjectPath<?, ?> path, |
| | | OptionalRelationDefinition<?, S> relation, |
| | | ServerManagedObjectAddListener<S> listener) { |
| | | this.path = path; |
| | | this.optionalRelation = relation; |
| | | this.instantiableRelation = null; |
| | | this.setRelation = null; |
| | | this.listener = listener; |
| | | this.cachedManagedObject = null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create a new configuration add listener adaptor for a |
| | | * set relation. |
| | | * |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | | * The set relation. |
| | | * @param listener |
| | | * The underlying add listener. |
| | | */ |
| | | public ConfigAddListenerAdaptor(ManagedObjectPath<?, ?> path, |
| | | SetRelationDefinition<?, S> relation, |
| | | ServerManagedObjectAddListener<S> listener) { |
| | | this.path = path; |
| | | this.instantiableRelation = null; |
| | | this.optionalRelation = null; |
| | | this.setRelation = relation; |
| | | this.listener = listener; |
| | | this.cachedManagedObject = null; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) { |
| | | if (optionalRelation != null) { |
| | | // Optional managed objects are located directly beneath the |
| | | // parent and have a well-defined name. We need to make sure |
| | | // that we are handling the correct entry. |
| | | ManagedObjectPath<?, ?> childPath = path.child(optionalRelation); |
| | | DN expectedDN = DNBuilder.create(childPath); |
| | | if (!configEntry.getDN().equals(expectedDN)) { |
| | | // Doesn't apply to us. |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | /** |
| | | * Create a new configuration add listener adaptor for an instantiable |
| | | * relation. |
| | | * |
| | | * @param context |
| | | * The server context. |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | | * The instantiable relation. |
| | | * @param listener |
| | | * The underlying add listener. |
| | | */ |
| | | public ConfigAddListenerAdaptor(ServerManagementContext context, ManagedObjectPath<?, ?> path, |
| | | InstantiableRelationDefinition<?, S> relation, ServerManagedObjectAddListener<S> listener) { |
| | | this.serverContext = context; |
| | | this.path = path; |
| | | this.instantiableRelation = relation; |
| | | this.optionalRelation = null; |
| | | this.setRelation = null; |
| | | this.listener = listener; |
| | | this.cachedManagedObject = null; |
| | | } |
| | | |
| | | // Cached objects are guaranteed to be from previous acceptable |
| | | // callback. |
| | | ConfigChangeResult result = listener |
| | | .applyConfigurationAdd(cachedManagedObject); |
| | | /** |
| | | * Create a new configuration add listener adaptor for an optional relation. |
| | | * |
| | | * @param context |
| | | * The server context. |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | | * The optional relation. |
| | | * @param listener |
| | | * The underlying add listener. |
| | | */ |
| | | public ConfigAddListenerAdaptor(ServerManagementContext context, ManagedObjectPath<?, ?> path, |
| | | OptionalRelationDefinition<?, S> relation, ServerManagedObjectAddListener<S> listener) { |
| | | this.serverContext = context; |
| | | this.path = path; |
| | | this.optionalRelation = relation; |
| | | this.instantiableRelation = null; |
| | | this.setRelation = null; |
| | | this.listener = listener; |
| | | this.cachedManagedObject = null; |
| | | } |
| | | |
| | | // Now apply post constraint call-backs. |
| | | if (result.getResultCode() == ResultCode.SUCCESS) { |
| | | ManagedObjectDefinition<?, ?> d = cachedManagedObject |
| | | .getManagedObjectDefinition(); |
| | | for (Constraint constraint : d.getAllConstraints()) { |
| | | for (ServerConstraintHandler handler : constraint |
| | | .getServerConstraintHandlers()) { |
| | | try { |
| | | handler.performPostAdd(cachedManagedObject); |
| | | } catch (ConfigException e) { |
| | | debugLogger.trace("Unable to perform post add", e); |
| | | } |
| | | /** |
| | | * Create a new configuration add listener adaptor for a set relation. |
| | | * |
| | | * @param context |
| | | * The server context. |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | | * The set relation. |
| | | * @param listener |
| | | * The underlying add listener. |
| | | */ |
| | | public ConfigAddListenerAdaptor(ServerManagementContext context, ManagedObjectPath<?, ?> path, |
| | | SetRelationDefinition<?, S> relation, ServerManagedObjectAddListener<S> listener) { |
| | | this.serverContext = context; |
| | | this.path = path; |
| | | this.instantiableRelation = null; |
| | | this.optionalRelation = null; |
| | | this.setRelation = relation; |
| | | this.listener = listener; |
| | | this.cachedManagedObject = null; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(Entry configEntry) { |
| | | if (optionalRelation != null) { |
| | | // Optional managed objects are located directly beneath the |
| | | // parent and have a well-defined name. We need to make sure |
| | | // that we are handling the correct entry. |
| | | ManagedObjectPath<?, ?> childPath = path.child(optionalRelation); |
| | | DN expectedDN = DNBuilder.create(childPath); |
| | | if (!configEntry.getName().equals(expectedDN)) { |
| | | // Doesn't apply to us. |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Cached objects are guaranteed to be from previous acceptable |
| | | // callback. |
| | | ConfigChangeResult result = listener.applyConfigurationAdd(cachedManagedObject); |
| | | |
| | | // Now apply post constraint call-backs. |
| | | if (result.getResultCode() == ResultCode.SUCCESS) { |
| | | ManagedObjectDefinition<?, ?> d = cachedManagedObject.getManagedObjectDefinition(); |
| | | for (Constraint constraint : d.getAllConstraints()) { |
| | | for (ServerConstraintHandler handler : constraint.getServerConstraintHandlers()) { |
| | | try { |
| | | handler.performPostAdd(cachedManagedObject); |
| | | } catch (ConfigException e) { |
| | | debugLogger.trace("Unable to perform post add", e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configAddIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | DN dn = configEntry.getName(); |
| | | String name = dn.rdn().getFirstAVA().getAttributeValue().toString().trim(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, |
| | | LocalizableMessageBuilder unacceptableReason) { |
| | | DN dn = configEntry.getDN(); |
| | | String name = dn.rdn().getFirstAVA().getAttributeValue().toString().trim(); |
| | | |
| | | try { |
| | | ManagedObjectPath<?, ? extends S> childPath; |
| | | if (instantiableRelation != null) { |
| | | childPath = path.child(instantiableRelation, name); |
| | | } else if (setRelation != null) { |
| | | try { |
| | | childPath = path.child(setRelation, name); |
| | | } catch (IllegalArgumentException e) { |
| | | throw new DefinitionDecodingException(setRelation |
| | | .getChildDefinition(), Reason.WRONG_TYPE_INFORMATION); |
| | | ManagedObjectPath<?, ? extends S> childPath; |
| | | if (instantiableRelation != null) { |
| | | childPath = path.child(instantiableRelation, name); |
| | | } else if (setRelation != null) { |
| | | try { |
| | | childPath = path.child(setRelation, name); |
| | | } catch (IllegalArgumentException e) { |
| | | throw new DefinitionDecodingException(setRelation.getChildDefinition(), |
| | | Reason.WRONG_TYPE_INFORMATION); |
| | | } |
| | | } else { |
| | | // Optional managed objects are located directly beneath the |
| | | // parent and have a well-defined name. We need to make sure |
| | | // that we are handling the correct entry. |
| | | childPath = path.child(optionalRelation); |
| | | DN expectedDN = DNBuilder.create(childPath); |
| | | if (!dn.equals(expectedDN)) { |
| | | // Doesn't apply to us. |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | cachedManagedObject = serverContext.decode(childPath, configEntry, configEntry); |
| | | } catch (DecodingException e) { |
| | | unacceptableReason.append(e.getMessageObject()); |
| | | return false; |
| | | } |
| | | } else { |
| | | // Optional managed objects are located directly beneath the |
| | | // parent and have a well-defined name. We need to make sure |
| | | // that we are handling the correct entry. |
| | | childPath = path.child(optionalRelation); |
| | | DN expectedDN = DNBuilder.create(childPath); |
| | | if (!dn.equals(expectedDN)) { |
| | | // Doesn't apply to us. |
| | | return true; |
| | | |
| | | // Give up immediately if a constraint violation occurs. |
| | | try { |
| | | cachedManagedObject.ensureIsUsable(); |
| | | } catch (ConstraintViolationException e) { |
| | | generateUnacceptableReason(e.getMessages(), unacceptableReason); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | cachedManagedObject = context.decode(childPath, configEntry, configEntry); |
| | | } catch (DecodingException e) { |
| | | unacceptableReason.append(e.getMessageObject()); |
| | | return false; |
| | | // Let the add listener decide. |
| | | List<LocalizableMessage> reasons = new LinkedList<LocalizableMessage>(); |
| | | if (listener.isConfigurationAddAcceptable(cachedManagedObject, reasons)) { |
| | | return true; |
| | | } else { |
| | | generateUnacceptableReason(reasons, unacceptableReason); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // Give up immediately if a constraint violation occurs. |
| | | try { |
| | | cachedManagedObject.ensureIsUsable(); |
| | | } catch (ConstraintViolationException e) { |
| | | generateUnacceptableReason(e.getMessages(), unacceptableReason); |
| | | return false; |
| | | /** |
| | | * Get the server managed object add listener associated with this adaptor. |
| | | * |
| | | * @return Returns the server managed object add listener associated with |
| | | * this adaptor. |
| | | */ |
| | | ServerManagedObjectAddListener<S> getServerManagedObjectAddListener() { |
| | | return listener; |
| | | } |
| | | |
| | | // Let the add listener decide. |
| | | List<LocalizableMessage> reasons = new LinkedList<LocalizableMessage>(); |
| | | if (listener.isConfigurationAddAcceptable(cachedManagedObject, reasons)) { |
| | | return true; |
| | | } else { |
| | | generateUnacceptableReason(reasons, unacceptableReason); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the server managed object add listener associated with this |
| | | * adaptor. |
| | | * |
| | | * @return Returns the server managed object add listener associated |
| | | * with this adaptor. |
| | | */ |
| | | ServerManagedObjectAddListener<S> getServerManagedObjectAddListener() { |
| | | return listener; |
| | | } |
| | | } |
| | |
| | | import org.opends.server.admin.UndefinedDefaultBehaviorProvider; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.config.ConfigurationRepository; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | |
| | | /** |
| | |
| | | * @param dependencies |
| | | * Add dependencies names to this collection. |
| | | */ |
| | | public static <T> void find(ManagedObjectPath<?, ?> path, PropertyDefinition<T> pd, Collection<DN> dependencies) { |
| | | public static <T> void find(ManagedObjectPath<?, ?> path, PropertyDefinition<T> pd, |
| | | Collection<DN> dependencies) { |
| | | Visitor<T> v = new Visitor<T>(dependencies); |
| | | DefaultBehaviorProvider<T> db = pd.getDefaultBehaviorProvider(); |
| | | db.accept(v, path); |
| | |
| | | } |
| | | } |
| | | |
| | | // Cached managed object between accept/apply call-backs. |
| | | /** Cached managed object between accept/apply call-backs. */ |
| | | private ServerManagedObject<? extends S> cachedManagedObject; |
| | | |
| | | // The delete listener which is used to remove this listener and any |
| | | // dependencies. |
| | | /** |
| | | * The delete listener which is used to remove this listener and any |
| | | * dependencies. |
| | | */ |
| | | private final ConfigDeleteListener cleanerListener; |
| | | |
| | | // The names of entries that this change listener depends on. |
| | | /** The names of entries that this change listener depends on. */ |
| | | private final Set<DN> dependencies; |
| | | |
| | | // The listener used to notify this listener when dependency entries |
| | | // are modified. |
| | | /** |
| | | * The listener used to notify this listener when dependency entries are |
| | | * modified. |
| | | */ |
| | | private final ConfigChangeListener dependencyListener; |
| | | |
| | | // The DN associated with this listener. |
| | | /** The DN associated with this listener. */ |
| | | private final DN dn; |
| | | |
| | | // The underlying change listener. |
| | | /** The underlying change listener. */ |
| | | private final ServerManagedObjectChangeListener<? super S> listener; |
| | | |
| | | // The managed object path. |
| | | /** The managed object path. */ |
| | | private final ManagedObjectPath<?, S> path; |
| | | |
| | | /** Repository of configuration entries */ |
| | | private final ConfigurationRepository configRepository; |
| | | |
| | | private final ServerManagementContext serverContext; |
| | | |
| | | /** |
| | | * Create a new configuration change listener adaptor. |
| | | * |
| | | * @param serverContext |
| | | * The server context. |
| | | * @param path |
| | | * The managed object path. |
| | | * @param listener |
| | | * The underlying change listener. |
| | | */ |
| | | public ConfigChangeListenerAdaptor(ManagedObjectPath<?, S> path, |
| | | ServerManagedObjectChangeListener<? super S> listener) { |
| | | public ConfigChangeListenerAdaptor(final ServerManagementContext serverContext, |
| | | final ManagedObjectPath<?, S> path, final ServerManagedObjectChangeListener<? super S> listener) { |
| | | this.serverContext = serverContext; |
| | | configRepository = serverContext.getConfigRepository(); |
| | | this.path = path; |
| | | this.dn = DNBuilder.create(path); |
| | | this.listener = listener; |
| | |
| | | this.dependencies = new HashSet<DN>(); |
| | | this.dependencyListener = new ConfigChangeListener() { |
| | | |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) { |
| | | ConfigEntry dependentConfigEntry = getConfigEntry(dn); |
| | | public ConfigChangeResult applyConfigurationChange(Entry configEntry) { |
| | | Entry dependentConfigEntry = getConfigEntry(dn); |
| | | if (dependentConfigEntry != null) { |
| | | return ConfigChangeListenerAdaptor.this.applyConfigurationChange(dependentConfigEntry); |
| | | } else { |
| | | // The dependent entry was not found. |
| | | configEntry.deregisterChangeListener(this); |
| | | configRepository.deregisterChangeListener(configEntry.getName(), this); |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | } |
| | | |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, |
| | | LocalizableMessageBuilder unacceptableReason) { |
| | | ConfigEntry dependentConfigEntry = getConfigEntry(dn); |
| | | public boolean configChangeIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | Entry dependentConfigEntry = getConfigEntry(dn); |
| | | if (dependentConfigEntry != null) { |
| | | return ConfigChangeListenerAdaptor.this.configChangeIsAcceptable(dependentConfigEntry, |
| | | unacceptableReason, configEntry); |
| | | } else { |
| | | // The dependent entry was not found. |
| | | configEntry.deregisterChangeListener(this); |
| | | configRepository.deregisterChangeListener(configEntry.getName(), this); |
| | | return true; |
| | | } |
| | | } |
| | |
| | | // Be careful not to register listeners against the dependent |
| | | // entry itself. |
| | | if (!entryDN.equals(dn)) { |
| | | ConfigEntry configEntry = getConfigEntry(entryDN); |
| | | Entry configEntry = getConfigEntry(entryDN); |
| | | if (configEntry != null) { |
| | | configEntry.registerChangeListener(dependencyListener); |
| | | configRepository.registerChangeListener(configEntry.getName(), dependencyListener); |
| | | } |
| | | } |
| | | } |
| | |
| | | // entry is removed. |
| | | this.cleanerListener = new ConfigDeleteListener() { |
| | | |
| | | public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) { |
| | | public ConfigChangeResult applyConfigurationDelete(Entry configEntry) { |
| | | // Perform finalization if the deleted entry is the monitored |
| | | // entry. |
| | | if (configEntry.getDN().equals(dn)) { |
| | | if (configEntry.getName().equals(dn)) { |
| | | finalizeChangeListener(); |
| | | } |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, |
| | | LocalizableMessageBuilder unacceptableReason) { |
| | | public boolean configDeleteIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | // Always acceptable. |
| | | return true; |
| | | } |
| | |
| | | |
| | | DN parent = dn.parent(); |
| | | if (parent != null) { |
| | | ConfigEntry configEntry = getConfigEntry(dn.parent()); |
| | | Entry configEntry = getConfigEntry(dn.parent()); |
| | | if (configEntry != null) { |
| | | configEntry.registerDeleteListener(cleanerListener); |
| | | configRepository.registerDeleteListener(configEntry.getName(), cleanerListener); |
| | | } |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) { |
| | | public ConfigChangeResult applyConfigurationChange(Entry configEntry) { |
| | | // Looking at the ConfigFileHandler implementation reveals |
| | | // that this ConfigEntry will actually be a different object to |
| | | // the one passed in the previous call-back (it will have the same |
| | | // content though). This configuration entry has the correct |
| | | // listener lists. |
| | | cachedManagedObject.setConfigEntry(configEntry); |
| | | cachedManagedObject.setConfigDN(configEntry.getName()); |
| | | |
| | | ConfigChangeResult result = listener.applyConfigurationChange(cachedManagedObject); |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | public boolean configChangeIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | return configChangeIsAcceptable(configEntry, unacceptableReason, configEntry); |
| | | } |
| | | |
| | |
| | | * @return <CODE>true</CODE> if the proposed entry contains an acceptable |
| | | * configuration, or <CODE>false</CODE> if it does not. |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason, |
| | | ConfigEntry newConfigEntry) { |
| | | public boolean configChangeIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason, |
| | | Entry newConfigEntry) { |
| | | try { |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | cachedManagedObject = context.decode(path, configEntry, newConfigEntry); |
| | | cachedManagedObject = serverContext.decode(path, configEntry, newConfigEntry); |
| | | } catch (DecodingException e) { |
| | | unacceptableReason.append(e.getMessageObject()); |
| | | return false; |
| | |
| | | public void finalizeChangeListener() { |
| | | // Remove the dependency listeners. |
| | | for (DN dependency : dependencies) { |
| | | ConfigEntry listenerConfigEntry = getConfigEntry(dependency); |
| | | Entry listenerConfigEntry = getConfigEntry(dependency); |
| | | if (listenerConfigEntry != null) { |
| | | listenerConfigEntry.deregisterChangeListener(dependencyListener); |
| | | configRepository.deregisterChangeListener(listenerConfigEntry.getName(), dependencyListener); |
| | | } |
| | | } |
| | | |
| | | // Now remove the cleaner listener as it will no longer be |
| | | // needed. |
| | | ConfigEntry parentConfigEntry = getConfigEntry(dn.parent()); |
| | | Entry parentConfigEntry = getConfigEntry(dn.parent()); |
| | | if (parentConfigEntry != null) { |
| | | parentConfigEntry.deregisterDeleteListener(cleanerListener); |
| | | configRepository.deregisterDeleteListener(parentConfigEntry.getName(), cleanerListener); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | // Returns the named configuration entry or null if it could not be |
| | | // retrieved. |
| | | private ConfigEntry getConfigEntry(DN dn) { |
| | | private Entry getConfigEntry(DN dn) { |
| | | try { |
| | | ConfigEntry configEntry = DirectoryServer.getConfigEntry(dn); |
| | | if (configEntry != null) { |
| | | return configEntry; |
| | | if (configRepository.hasEntry(dn)) { |
| | | return configRepository.getEntry(dn); |
| | | } else { |
| | | adminLogger.error(ERR_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST, String.valueOf(dn)); |
| | | } |
| | |
| | | adminLogger.error(ERR_ADMIN_CANNOT_GET_MANAGED_OBJECT, String.valueOf(dn), |
| | | StaticUtils.getExceptionMessage(e)); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | |
| | | import org.opends.server.admin.SetRelationDefinition; |
| | | import org.opends.server.admin.DefinitionDecodingException.Reason; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | |
| | | // The managed object path of the parent. |
| | | private final ManagedObjectPath<?, ?> path; |
| | | |
| | | private final ServerManagementContext serverContext; |
| | | |
| | | /** |
| | | * Create a new configuration delete listener adaptor for an instantiable |
| | | * relation. |
| | | * |
| | | * @param serverContext |
| | | * The server context. |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | |
| | | * @param listener |
| | | * The underlying delete listener. |
| | | */ |
| | | public ConfigDeleteListenerAdaptor(ManagedObjectPath<?, ?> path, InstantiableRelationDefinition<?, S> relation, |
| | | ServerManagedObjectDeleteListener<S> listener) { |
| | | public ConfigDeleteListenerAdaptor(ServerManagementContext serverContext, ManagedObjectPath<?, ?> path, |
| | | InstantiableRelationDefinition<?, S> relation, ServerManagedObjectDeleteListener<S> listener) { |
| | | this.serverContext = serverContext; |
| | | this.path = path; |
| | | this.optionalRelation = null; |
| | | this.instantiableRelation = relation; |
| | |
| | | /** |
| | | * Create a new configuration delete listener adaptor for an optional |
| | | * relation. |
| | | * |
| | | * @param serverContext TODO |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | |
| | | * @param listener |
| | | * The underlying delete listener. |
| | | */ |
| | | public ConfigDeleteListenerAdaptor(ManagedObjectPath<?, ?> path, OptionalRelationDefinition<?, S> relation, |
| | | ServerManagedObjectDeleteListener<S> listener) { |
| | | public ConfigDeleteListenerAdaptor(ServerManagementContext serverContext, ManagedObjectPath<?, ?> path, |
| | | OptionalRelationDefinition<?, S> relation, ServerManagedObjectDeleteListener<S> listener) { |
| | | this.serverContext = serverContext; |
| | | this.path = path; |
| | | this.optionalRelation = relation; |
| | | this.instantiableRelation = null; |
| | |
| | | |
| | | /** |
| | | * Create a new configuration delete listener adaptor for an set relation. |
| | | * |
| | | * @param serverContext TODO |
| | | * @param path |
| | | * The managed object path of the parent. |
| | | * @param relation |
| | |
| | | * @param listener |
| | | * The underlying delete listener. |
| | | */ |
| | | public ConfigDeleteListenerAdaptor(ManagedObjectPath<?, ?> path, SetRelationDefinition<?, S> relation, |
| | | ServerManagedObjectDeleteListener<S> listener) { |
| | | public ConfigDeleteListenerAdaptor(ServerManagementContext serverContext, ManagedObjectPath<?, ?> path, |
| | | SetRelationDefinition<?, S> relation, ServerManagedObjectDeleteListener<S> listener) { |
| | | this.serverContext = serverContext; |
| | | this.path = path; |
| | | this.optionalRelation = null; |
| | | this.instantiableRelation = null; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) { |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationDelete(Entry configEntry) { |
| | | if (optionalRelation != null) { |
| | | // Optional managed objects are located directly beneath the |
| | | // parent and have a well-defined name. We need to make sure |
| | | // that we are handling the correct entry. |
| | | ManagedObjectPath<?, ?> childPath = path.child(optionalRelation); |
| | | DN expectedDN = DNBuilder.create(childPath); |
| | | if (!configEntry.getDN().equals(expectedDN)) { |
| | | if (!configEntry.getName().equals(expectedDN)) { |
| | | // Doesn't apply to us. |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | DN dn = configEntry.getDN(); |
| | | public boolean configDeleteIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | DN dn = configEntry.getName(); |
| | | String name = dn.rdn().getFirstAVA().getAttributeValue().toString().trim(); |
| | | |
| | | try { |
| | |
| | | } |
| | | } |
| | | |
| | | ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | cachedManagedObject = context.decode(childPath, configEntry); |
| | | cachedManagedObject = serverContext.decode(childPath, configEntry); |
| | | } catch (DecodingException e) { |
| | | unacceptableReason.append(e.getMessageObject()); |
| | | return false; |
| | |
| | | |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.config.ConfigurationRepository; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | |
| | | // registered). |
| | | private final ConfigDeleteListener delayedDeleteListener; |
| | | |
| | | private final ConfigurationRepository configRepository; |
| | | |
| | | /** |
| | | * Create a new delayed add listener which will register an add listener |
| | | * with the specified entry when it is added. |
| | |
| | | * @param addListener |
| | | * The add listener to be added to the subordinate entry when it |
| | | * is added. |
| | | * @param configRepository TODO |
| | | */ |
| | | public DelayedConfigAddListener(DN child, ConfigAddListener addListener) { |
| | | public DelayedConfigAddListener(DN child, ConfigAddListener addListener, ConfigurationRepository configRepository) { |
| | | this.parent = child.parent(); |
| | | this.child = child; |
| | | this.delayedAddListener = addListener; |
| | | this.delayedDeleteListener = null; |
| | | this.configRepository = configRepository; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param deleteListener |
| | | * The delete listener to be added to the subordinate entry when |
| | | * it is added. |
| | | * @param configRepository TODO |
| | | */ |
| | | public DelayedConfigAddListener(DN child, ConfigDeleteListener deleteListener) { |
| | | public DelayedConfigAddListener(DN child, ConfigDeleteListener deleteListener, ConfigurationRepository configRepository) { |
| | | this.parent = child.parent(); |
| | | this.child = child; |
| | | this.delayedAddListener = null; |
| | | this.configRepository = configRepository; |
| | | this.delayedDeleteListener = deleteListener; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) { |
| | | if (configEntry.getDN().equals(child)) { |
| | | public ConfigChangeResult applyConfigurationAdd(Entry configEntry) { |
| | | if (configEntry.getName().equals(child)) { |
| | | // The subordinate entry matched our criteria so register the |
| | | // listener(s). |
| | | if (delayedAddListener != null) { |
| | | configEntry.registerAddListener(delayedAddListener); |
| | | configRepository.registerAddListener(configEntry.getName(), delayedAddListener); |
| | | } |
| | | |
| | | if (delayedDeleteListener != null) { |
| | | configEntry.registerDeleteListener(delayedDeleteListener); |
| | | configRepository.registerDeleteListener(configEntry.getName(), delayedDeleteListener); |
| | | } |
| | | |
| | | // We are no longer needed. |
| | | try { |
| | | ConfigEntry myEntry = DirectoryServer.getConfigEntry(parent); |
| | | if (myEntry != null) { |
| | | myEntry.deregisterAddListener(this); |
| | | // We are no longer needed. |
| | | if (configRepository.hasEntry(parent)) { |
| | | configRepository.deregisterAddListener(parent, this); |
| | | } |
| | | } catch (ConfigException e) { |
| | | debugLogger.trace("Unable to deregister add listener", e); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | public boolean configAddIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason) { |
| | | // Always acceptable. |
| | | return true; |
| | | } |
| | |
| | | package org.opends.server.admin.server; |
| | | |
| | | import static com.forgerock.opendj.ldap.AdminMessages.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.*; |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedList; |
| | |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.util.DynamicConstants; |
| | | import org.opends.server.config.ConfigurationRepository; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import com.forgerock.opendj.util.Pair; |
| | | |
| | | |
| | | /** |
| | | * A server-side managed object. |
| | |
| | | |
| | | private static final Logger logger = LoggerFactory.getLogger(ServerManagedObject.class); |
| | | |
| | | // The configuration entry associated with this server managed |
| | | // object (null if root). |
| | | private ConfigEntry configEntry; |
| | | /** |
| | | * The DN of configuration entry associated with this server managed object, |
| | | * which is {@code null} for root. |
| | | */ |
| | | private DN configDN; |
| | | |
| | | // The management context. |
| | | private final ServerManagementContext context = ServerManagementContext.getInstance(); |
| | | private final ServerManagementContext serverContext; |
| | | |
| | | // The managed object's definition. |
| | | private final ConfigurationRepository configRepository; |
| | | |
| | | private final ManagedObjectDefinition<?, S> definition; |
| | | |
| | | // The managed object path identifying this managed object's |
| | | // location. |
| | | /** The managed object path identifying this managed object's location */ |
| | | private final ManagedObjectPath<?, S> path; |
| | | |
| | | // The managed object's properties. |
| | | private final Map<PropertyDefinition<?>, SortedSet<?>> properties; |
| | | |
| | | /** |
| | |
| | | * The managed object definition. |
| | | * @param properties |
| | | * The managed object's properties. |
| | | * @param configEntry |
| | | * @param configDN |
| | | * The configuration entry associated with the managed object. |
| | | * @param context |
| | | * The server management context. |
| | | */ |
| | | ServerManagedObject(ManagedObjectPath<?, S> path, ManagedObjectDefinition<?, S> d, |
| | | Map<PropertyDefinition<?>, SortedSet<?>> properties, ConfigEntry configEntry) { |
| | | ServerManagedObject(final ManagedObjectPath<?, S> path, final ManagedObjectDefinition<?, S> d, |
| | | final Map<PropertyDefinition<?>, SortedSet<?>> properties, final DN configDN, |
| | | final ServerManagementContext context) { |
| | | this.definition = d; |
| | | this.path = path; |
| | | this.properties = properties; |
| | | this.configEntry = configEntry; |
| | | this.configDN = configDN; |
| | | this.serverContext = context; |
| | | this.configRepository = context.getConfigRepository(); |
| | | } |
| | | |
| | | /** |
| | |
| | | public <M extends Configuration> void deregisterAddListener(InstantiableRelationDefinition<?, M> d, |
| | | ConfigurationAddListener<M> listener) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | deregisterAddListener(baseDN, listener); |
| | | } |
| | |
| | | public <M extends Configuration> void deregisterAddListener(InstantiableRelationDefinition<?, M> d, |
| | | ServerManagedObjectAddListener<M> listener) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | deregisterAddListener(baseDN, listener); |
| | | } |
| | |
| | | public <M extends Configuration> void deregisterAddListener(OptionalRelationDefinition<?, M> d, |
| | | ConfigurationAddListener<M> listener) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | |
| | | DN baseDN = DNBuilder.create(path, d).parent(); |
| | | deregisterAddListener(baseDN, listener); |
| | | } |
| | |
| | | public <M extends Configuration> void deregisterAddListener(OptionalRelationDefinition<?, M> d, |
| | | ServerManagedObjectAddListener<M> listener) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | |
| | | DN baseDN = DNBuilder.create(path, d).parent(); |
| | | deregisterAddListener(baseDN, listener); |
| | | } |
| | |
| | | public <M extends Configuration> void deregisterAddListener(SetRelationDefinition<?, M> d, |
| | | ConfigurationAddListener<M> listener) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | deregisterAddListener(baseDN, listener); |
| | | } |
| | |
| | | public <M extends Configuration> void deregisterAddListener(SetRelationDefinition<?, M> d, |
| | | ServerManagedObjectAddListener<M> listener) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | deregisterAddListener(baseDN, listener); |
| | | } |
| | |
| | | * The configuration change listener. |
| | | */ |
| | | public void deregisterChangeListener(ConfigurationChangeListener<? super S> listener) { |
| | | for (ConfigChangeListener l : configEntry.getChangeListeners()) { |
| | | for (ConfigChangeListener l : configRepository.getChangeListeners(configDN)) { |
| | | if (l instanceof ConfigChangeListenerAdaptor) { |
| | | ConfigChangeListenerAdaptor<?> adaptor = (ConfigChangeListenerAdaptor<?>) l; |
| | | ServerManagedObjectChangeListener<?> l2 = adaptor.getServerManagedObjectChangeListener(); |
| | |
| | | ServerManagedObjectChangeListenerAdaptor<?> adaptor2 = (ServerManagedObjectChangeListenerAdaptor<?>) l2; |
| | | if (adaptor2.getConfigurationChangeListener() == listener) { |
| | | adaptor.finalizeChangeListener(); |
| | | configEntry.deregisterChangeListener(adaptor); |
| | | configRepository.deregisterChangeListener(configDN, adaptor); |
| | | } |
| | | } |
| | | } |
| | |
| | | * The server managed object change listener. |
| | | */ |
| | | public void deregisterChangeListener(ServerManagedObjectChangeListener<? super S> listener) { |
| | | for (ConfigChangeListener l : configEntry.getChangeListeners()) { |
| | | for (ConfigChangeListener l : configRepository.getChangeListeners(configDN)) { |
| | | if (l instanceof ConfigChangeListenerAdaptor) { |
| | | ConfigChangeListenerAdaptor<?> adaptor = (ConfigChangeListenerAdaptor<?>) l; |
| | | if (adaptor.getServerManagedObjectChangeListener() == listener) { |
| | | adaptor.finalizeChangeListener(); |
| | | configEntry.deregisterChangeListener(adaptor); |
| | | configRepository.deregisterChangeListener(configDN, adaptor); |
| | | } |
| | | } |
| | | } |
| | |
| | | public <M extends Configuration> ServerManagedObject<? extends M> getChild(InstantiableRelationDefinition<?, M> d, |
| | | String name) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | return context.getManagedObject(path.child(d, name)); |
| | | return serverContext.getManagedObject(path.child(d, name)); |
| | | } |
| | | |
| | | /** |
| | |
| | | public <M extends Configuration> ServerManagedObject<? extends M> getChild(OptionalRelationDefinition<?, M> d) |
| | | throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | return context.getManagedObject(path.child(d)); |
| | | return serverContext.getManagedObject(path.child(d)); |
| | | } |
| | | |
| | | /** |
| | |
| | | String name) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | |
| | | return context.getManagedObject(path.child(d, name)); |
| | | return serverContext.getManagedObject(path.child(d, name)); |
| | | } |
| | | |
| | | /** |
| | |
| | | public <M extends Configuration> ServerManagedObject<? extends M> getChild(SingletonRelationDefinition<?, M> d) |
| | | throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | return context.getManagedObject(path.child(d)); |
| | | return serverContext.getManagedObject(path.child(d)); |
| | | } |
| | | |
| | | /** |
| | | * Returns the server management context used by this object. |
| | | * |
| | | * @return the context |
| | | */ |
| | | public ServerManagementContext getServerContext() { |
| | | return serverContext; |
| | | } |
| | | |
| | | /** |
| | |
| | | * managed object, or an null DN if this is the root managed object. |
| | | */ |
| | | public DN getDN() { |
| | | if (configEntry != null) { |
| | | return configEntry.getDN(); |
| | | if (configDN != null) { |
| | | return configDN; |
| | | } else { |
| | | return DN.rootDN(); |
| | | } |
| | |
| | | */ |
| | | public boolean hasChild(OptionalRelationDefinition<?, ?> d) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | return context.managedObjectExists(path.child(d)); |
| | | return serverContext.managedObjectExists(path.child(d)); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public String[] listChildren(InstantiableRelationDefinition<?, ?> d) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | return context.listManagedObjects(path, d); |
| | | return serverContext.listManagedObjects(path, d); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public String[] listChildren(SetRelationDefinition<?, ?> d) throws IllegalArgumentException { |
| | | validateRelationDefinition(d); |
| | | return context.listManagedObjects(path, d); |
| | | return serverContext.listManagedObjects(path, d); |
| | | } |
| | | |
| | | /** |
| | |
| | | ServerManagedObjectAddListener<M> listener) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d, listener); |
| | | ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(serverContext, path, d, listener); |
| | | registerAddListener(baseDN, adaptor); |
| | | } |
| | | |
| | |
| | | ServerManagedObjectAddListener<M> listener) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | DN baseDN = DNBuilder.create(path, d).parent(); |
| | | ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d, listener); |
| | | ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(serverContext, path, d, listener); |
| | | registerAddListener(baseDN, adaptor); |
| | | } |
| | | |
| | |
| | | ServerManagedObjectAddListener<M> listener) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d, listener); |
| | | ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(serverContext, path, d, listener); |
| | | registerAddListener(baseDN, adaptor); |
| | | } |
| | | |
| | |
| | | * The server managed object change listener. |
| | | */ |
| | | public void registerChangeListener(ServerManagedObjectChangeListener<? super S> listener) { |
| | | ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(path, listener); |
| | | configEntry.registerChangeListener(adaptor); |
| | | |
| | | ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(serverContext, path, listener); |
| | | configRepository.registerChangeListener(configDN, adaptor); |
| | | |
| | | // TODO : go toward this |
| | | // Entry entry; |
| | |
| | | ServerManagedObjectDeleteListener<M> listener) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d, listener); |
| | | ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(serverContext, path, d, listener); |
| | | registerDeleteListener(baseDN, adaptor); |
| | | } |
| | | |
| | |
| | | ServerManagedObjectDeleteListener<M> listener) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | DN baseDN = DNBuilder.create(path, d).parent(); |
| | | ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d, listener); |
| | | ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(serverContext, path, d, listener); |
| | | registerDeleteListener(baseDN, adaptor); |
| | | } |
| | | |
| | |
| | | ServerManagedObjectDeleteListener<M> listener) throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | DN baseDN = DNBuilder.create(path, d); |
| | | ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d, listener); |
| | | ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(serverContext, path, d, listener); |
| | | registerDeleteListener(baseDN, adaptor); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * Update the config entry associated with this server managed object. This |
| | | * Update the config DN associated with this server managed object. This |
| | | * is only intended to be used by change listener call backs in order to |
| | | * update the managed object with the correct config entry. |
| | | * update the managed object with the correct config DN. |
| | | * |
| | | * @param configEntry |
| | | * The configuration entry. |
| | | * @param configDN |
| | | * The DN of the underlying configuration entry. |
| | | */ |
| | | void setConfigEntry(ConfigEntry configEntry) { |
| | | this.configEntry = configEntry; |
| | | void setConfigDN(DN configDN) { |
| | | this.configDN = configDN; |
| | | } |
| | | |
| | | // Deregister an add listener. |
| | | private <M extends Configuration> void deregisterAddListener(DN baseDN, ConfigurationAddListener<M> listener) { |
| | | try { |
| | | ConfigEntry configEntry = getListenerConfigEntry(baseDN); |
| | | if (configEntry != null) { |
| | | for (ConfigAddListener l : configEntry.getAddListeners()) { |
| | | if (l instanceof ConfigAddListenerAdaptor) { |
| | | ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) l; |
| | | ServerManagedObjectAddListener<?> l2 = adaptor.getServerManagedObjectAddListener(); |
| | | if (l2 instanceof ServerManagedObjectAddListenerAdaptor<?>) { |
| | | ServerManagedObjectAddListenerAdaptor<?> adaptor2 = (ServerManagedObjectAddListenerAdaptor<?>) l2; |
| | | if (configRepository.hasEntry(baseDN)) { |
| | | for (ConfigAddListener configListener : configRepository.getAddListeners(baseDN)) { |
| | | if (configListener instanceof ConfigAddListenerAdaptor) { |
| | | ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) configListener; |
| | | ServerManagedObjectAddListener<?> smoListener = adaptor.getServerManagedObjectAddListener(); |
| | | if (smoListener instanceof ServerManagedObjectAddListenerAdaptor<?>) { |
| | | ServerManagedObjectAddListenerAdaptor<?> adaptor2 = (ServerManagedObjectAddListenerAdaptor<?>) smoListener; |
| | | if (adaptor2.getConfigurationAddListener() == listener) { |
| | | configEntry.deregisterAddListener(adaptor); |
| | | configRepository.deregisterAddListener(baseDN, adaptor); |
| | | } |
| | | } |
| | | } |
| | |
| | | // Deregister an add listener. |
| | | private <M extends Configuration> void deregisterAddListener(DN baseDN, ServerManagedObjectAddListener<M> listener) { |
| | | try { |
| | | ConfigEntry configEntry = getListenerConfigEntry(baseDN); |
| | | if (configEntry != null) { |
| | | for (ConfigAddListener l : configEntry.getAddListeners()) { |
| | | if (l instanceof ConfigAddListenerAdaptor) { |
| | | ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) l; |
| | | if (configRepository.hasEntry(baseDN)) { |
| | | for (ConfigAddListener configListener : configRepository.getAddListeners(baseDN)) { |
| | | if (configListener instanceof ConfigAddListenerAdaptor) { |
| | | ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) configListener; |
| | | if (adaptor.getServerManagedObjectAddListener() == listener) { |
| | | configEntry.deregisterAddListener(adaptor); |
| | | configRepository.deregisterAddListener(baseDN, adaptor); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Convenience method to retrieve the initial listener and its intermediate |
| | | * adaptor from the provided configListener. |
| | | * |
| | | * @param <T> |
| | | * Type of the configuration. |
| | | * @param configListener |
| | | * Listener from wich to extract the initial listener. |
| | | * @return a pair of (intermediate adaptor, intermediate listener) or |
| | | * {@code Pair.EMPTY} if listener can't be extracted |
| | | */ |
| | | static <T extends Configuration> Pair<ConfigAddListenerAdaptor<T>, ConfigurationAddListener<T>> |
| | | extractInitialListener(ConfigAddListener configListener) { |
| | | Pair<ConfigAddListenerAdaptor<T>, ServerManagedObjectAddListener<T>> pair = |
| | | extractIntermediateListener(configListener); |
| | | if (!pair.equals(Pair.EMPTY) && pair.getSecond() instanceof ServerManagedObjectAddListenerAdaptor) { |
| | | ServerManagedObjectAddListenerAdaptor<T> adaptor2 = (ServerManagedObjectAddListenerAdaptor<T>) |
| | | pair.getSecond(); |
| | | return Pair.of(pair.getFirst(), adaptor2.getConfigurationAddListener()); |
| | | } |
| | | return Pair.empty(); |
| | | } |
| | | |
| | | /** |
| | | * Convenience method to retrieve the intermediate listener and its |
| | | * intermediate adaptor from the provided configListener. |
| | | * |
| | | * @param <T> |
| | | * Type of the configuration. |
| | | * @param configListener |
| | | * Listener from wich to extract the initial listener. |
| | | * @return a pair of (intermediate adaptor, initial listener) or |
| | | * {@code Pair.EMPTY} if listener can't be extracted |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | static <T extends Configuration> Pair<ConfigAddListenerAdaptor<T>, ServerManagedObjectAddListener<T>> |
| | | extractIntermediateListener(ConfigAddListener configListener) { |
| | | if (configListener instanceof ConfigAddListenerAdaptor) { |
| | | ConfigAddListenerAdaptor<T> adaptor = ((ConfigAddListenerAdaptor<T>) configListener); |
| | | return Pair.of(adaptor, adaptor.getServerManagedObjectAddListener()); |
| | | } |
| | | return Pair.empty(); |
| | | } |
| | | |
| | | // Deregister a delete listener. |
| | | private <M extends Configuration> void deregisterDeleteListener(DN baseDN, ConfigurationDeleteListener<M> listener) { |
| | | try { |
| | | ConfigEntry configEntry = getListenerConfigEntry(baseDN); |
| | | if (configEntry != null) { |
| | | for (ConfigDeleteListener l : configEntry.getDeleteListeners()) { |
| | | if (configRepository.hasEntry(baseDN)) { |
| | | for (ConfigDeleteListener l : configRepository.getDeleteListeners(baseDN)) { |
| | | if (l instanceof ConfigDeleteListenerAdaptor) { |
| | | ConfigDeleteListenerAdaptor<?> adaptor = (ConfigDeleteListenerAdaptor<?>) l; |
| | | ServerManagedObjectDeleteListener<?> l2 = adaptor.getServerManagedObjectDeleteListener(); |
| | | if (l2 instanceof ServerManagedObjectDeleteListenerAdaptor<?>) { |
| | | ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 = (ServerManagedObjectDeleteListenerAdaptor<?>) l2; |
| | | if (adaptor2.getConfigurationDeleteListener() == listener) { |
| | | configEntry.deregisterDeleteListener(adaptor); |
| | | configRepository.deregisterDeleteListener(baseDN, adaptor); |
| | | } |
| | | } |
| | | } |
| | |
| | | private <M extends Configuration> void deregisterDeleteListener(DN baseDN, |
| | | ServerManagedObjectDeleteListener<M> listener) { |
| | | try { |
| | | ConfigEntry configEntry = getListenerConfigEntry(baseDN); |
| | | if (configEntry != null) { |
| | | for (ConfigDeleteListener l : configEntry.getDeleteListeners()) { |
| | | if (configRepository.hasEntry(baseDN)) { |
| | | for (ConfigDeleteListener l : configRepository.getDeleteListeners(baseDN)) { |
| | | if (l instanceof ConfigDeleteListenerAdaptor) { |
| | | ConfigDeleteListenerAdaptor<?> adaptor = (ConfigDeleteListenerAdaptor<?>) l; |
| | | if (adaptor.getServerManagedObjectDeleteListener() == listener) { |
| | | configEntry.deregisterDeleteListener(adaptor); |
| | | configRepository.deregisterDeleteListener(baseDN, adaptor); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | // Gets a config entry required for a listener and throws a config |
| | | // exception on failure or returns null if the entry does not exist. |
| | | private ConfigEntry getListenerConfigEntry(DN dn) throws ConfigException { |
| | | // Attempt to retrieve the listener base entry. |
| | | ConfigEntry configEntry; |
| | | try { |
| | | configEntry = DirectoryServer.getConfigEntry(dn); |
| | | } catch (ConfigException e) { |
| | | logger.trace("Unable to get listener base entry", e); |
| | | LocalizableMessage message = ERR_ADMIN_CANNOT_GET_LISTENER_BASE.get(String.valueOf(dn), |
| | | stackTraceToSingleLineString(e, DynamicConstants.DEBUG_BUILD)); |
| | | throw new ConfigException(message, e); |
| | | } |
| | | |
| | | return configEntry; |
| | | } |
| | | |
| | | // Register an instantiable or optional relation add listener. |
| | | private void registerAddListener(DN baseDN, ConfigAddListener adaptor) throws IllegalArgumentException, |
| | | ConfigException { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(baseDN); |
| | | |
| | | if (relationEntry != null) { |
| | | relationEntry.registerAddListener(adaptor); |
| | | if (configRepository.hasEntry(baseDN)) { |
| | | configRepository.registerAddListener(baseDN, adaptor); |
| | | } else { |
| | | // The relation entry does not exist yet so register a delayed |
| | | // add listener. |
| | | ConfigAddListener delayedListener = new DelayedConfigAddListener(baseDN, adaptor); |
| | | // The relation entry does not exist yet |
| | | // so register a delayed add listener. |
| | | ConfigAddListener delayedListener = new DelayedConfigAddListener(baseDN, adaptor, configRepository); |
| | | registerDelayedListener(baseDN, delayedListener); |
| | | } |
| | | } |
| | |
| | | // Register a delayed listener with the nearest existing parent |
| | | // entry to the provided base DN. |
| | | private void registerDelayedListener(DN baseDN, ConfigAddListener delayedListener) throws ConfigException { |
| | | DN parentDN = baseDN.parent(); |
| | | while (parentDN != null) { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(parentDN); |
| | | if (relationEntry == null) { |
| | | delayedListener = new DelayedConfigAddListener(parentDN, delayedListener); |
| | | parentDN = parentDN.parent(); |
| | | DN currentDN = baseDN.parent(); |
| | | DN previousDN = currentDN; |
| | | while (currentDN != null) { |
| | | if (!configRepository.hasEntry(currentDN)) { |
| | | delayedListener = new DelayedConfigAddListener(currentDN, delayedListener, configRepository); |
| | | previousDN = currentDN; |
| | | currentDN = currentDN.parent(); |
| | | } else { |
| | | relationEntry.registerAddListener(delayedListener); |
| | | configRepository.registerAddListener(previousDN, delayedListener); |
| | | return; |
| | | } |
| | | } |
| | |
| | | DN parentDN = baseDN.parent(); |
| | | int delayWrappers = 0; |
| | | while (parentDN != null) { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(parentDN); |
| | | if (relationEntry == null) { |
| | | if (!configRepository.hasEntry(parentDN)) { |
| | | parentDN = parentDN.parent(); |
| | | delayWrappers++; |
| | | } else { |
| | | for (ConfigAddListener l : relationEntry.getAddListeners()) { |
| | | if (l instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) l; |
| | | for (ConfigAddListener configListener : configRepository.getAddListeners(parentDN)) { |
| | | if (configListener instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) configListener; |
| | | ConfigAddListener wrappedListener; |
| | | |
| | | int i = delayWrappers; |
| | | for (; i > 0; i--) { |
| | | wrappedListener = delayListener.getDelayedAddListener(); |
| | | if (wrappedListener != null && wrappedListener instanceof DelayedConfigAddListener) { |
| | | delayListener = (DelayedConfigAddListener) l; |
| | | delayListener = (DelayedConfigAddListener) configListener; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (i > 0) { |
| | | // There are not enough level of wrapping so this |
| | | // can't be |
| | | // the listener we are looking for. |
| | | // There are not enough level of wrapping |
| | | // so this can't be the listener we are looking for. |
| | | continue; |
| | | } |
| | | |
| | |
| | | if (l2 instanceof ServerManagedObjectAddListenerAdaptor<?>) { |
| | | ServerManagedObjectAddListenerAdaptor<?> adaptor2 = (ServerManagedObjectAddListenerAdaptor<?>) l2; |
| | | if (adaptor2.getConfigurationAddListener() == listener) { |
| | | relationEntry.deregisterAddListener(l); |
| | | configRepository.deregisterAddListener(parentDN, configListener); |
| | | } |
| | | } |
| | | } |
| | |
| | | DN parentDN = baseDN.parent(); |
| | | int delayWrappers = 0; |
| | | while (parentDN != null) { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(parentDN); |
| | | if (relationEntry == null) { |
| | | if (!configRepository.hasEntry(parentDN)) { |
| | | parentDN = parentDN.parent(); |
| | | delayWrappers++; |
| | | } else { |
| | | for (ConfigAddListener l : relationEntry.getAddListeners()) { |
| | | for (ConfigAddListener l : configRepository.getAddListeners(parentDN)) { |
| | | if (l instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) l; |
| | | ConfigAddListener wrappedListener; |
| | |
| | | } |
| | | |
| | | if (i > 0) { |
| | | // There are not enough level of wrapping so this |
| | | // can't be |
| | | // the listener we are looking for. |
| | | // There are not enough level of wrapping |
| | | // so this can't be the listener we are looking for. |
| | | continue; |
| | | } |
| | | |
| | |
| | | if (l2 instanceof ServerManagedObjectDeleteListenerAdaptor<?>) { |
| | | ServerManagedObjectDeleteListenerAdaptor<?> adaptor2 = (ServerManagedObjectDeleteListenerAdaptor<?>) l2; |
| | | if (adaptor2.getConfigurationDeleteListener() == listener) { |
| | | relationEntry.deregisterAddListener(l); |
| | | configRepository.deregisterAddListener(parentDN, l); |
| | | } |
| | | } |
| | | } |
| | |
| | | DN parentDN = baseDN.parent(); |
| | | int delayWrappers = 0; |
| | | while (parentDN != null) { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(parentDN); |
| | | if (relationEntry == null) { |
| | | if (!configRepository.hasEntry(parentDN)) { |
| | | parentDN = parentDN.parent(); |
| | | delayWrappers++; |
| | | } else { |
| | | for (ConfigAddListener l : relationEntry.getAddListeners()) { |
| | | if (l instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) l; |
| | | for (ConfigAddListener configListener : configRepository.getAddListeners(parentDN)) { |
| | | if (configListener instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) configListener; |
| | | ConfigAddListener wrappedListener; |
| | | |
| | | int i = delayWrappers; |
| | | for (; i > 0; i--) { |
| | | wrappedListener = delayListener.getDelayedAddListener(); |
| | | if (wrappedListener != null && wrappedListener instanceof DelayedConfigAddListener) { |
| | | delayListener = (DelayedConfigAddListener) l; |
| | | delayListener = (DelayedConfigAddListener) configListener; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (i > 0) { |
| | | // There are not enough level of wrapping so this |
| | | // can't be |
| | | // the listener we are looking for. |
| | | // There are not enough level of wrapping |
| | | // so this can't be the listener we are looking for. |
| | | continue; |
| | | } |
| | | |
| | |
| | | if (delayedListener != null && delayedListener instanceof ConfigAddListenerAdaptor) { |
| | | ConfigAddListenerAdaptor<?> adaptor = (ConfigAddListenerAdaptor<?>) delayedListener; |
| | | if (adaptor.getServerManagedObjectAddListener() == listener) { |
| | | relationEntry.deregisterAddListener(l); |
| | | configRepository.deregisterAddListener(parentDN, configListener); |
| | | } |
| | | } |
| | | } |
| | |
| | | DN parentDN = baseDN.parent(); |
| | | int delayWrappers = 0; |
| | | while (parentDN != null) { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(parentDN); |
| | | if (relationEntry == null) { |
| | | if (!configRepository.hasEntry(parentDN)) { |
| | | parentDN = parentDN.parent(); |
| | | delayWrappers++; |
| | | } else { |
| | | for (ConfigAddListener l : relationEntry.getAddListeners()) { |
| | | if (l instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) l; |
| | | for (ConfigAddListener configListener : configRepository.getAddListeners(parentDN)) { |
| | | if (configListener instanceof DelayedConfigAddListener) { |
| | | DelayedConfigAddListener delayListener = (DelayedConfigAddListener) configListener; |
| | | ConfigAddListener wrappedListener; |
| | | |
| | | int i = delayWrappers; |
| | | for (; i > 0; i--) { |
| | | wrappedListener = delayListener.getDelayedAddListener(); |
| | | if (wrappedListener != null && wrappedListener instanceof DelayedConfigAddListener) { |
| | | delayListener = (DelayedConfigAddListener) l; |
| | | delayListener = (DelayedConfigAddListener) configListener; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (i > 0) { |
| | | // There are not enough level of wrapping so this |
| | | // can't be |
| | | // the listener we are looking for. |
| | | // There are not enough level of wrapping |
| | | // so this can't be the listener we are looking for. |
| | | continue; |
| | | } |
| | | |
| | |
| | | if (delayedListener != null && delayedListener instanceof ConfigDeleteListenerAdaptor) { |
| | | ConfigDeleteListenerAdaptor<?> adaptor = (ConfigDeleteListenerAdaptor<?>) delayedListener; |
| | | if (adaptor.getServerManagedObjectDeleteListener() == listener) { |
| | | relationEntry.deregisterAddListener(l); |
| | | configRepository.deregisterAddListener(parentDN, configListener); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | // Register an instantiable or optional relation delete listener. |
| | | private void registerDeleteListener(DN baseDN, ConfigDeleteListener adaptor) throws ConfigException { |
| | | ConfigEntry relationEntry = getListenerConfigEntry(baseDN); |
| | | |
| | | if (relationEntry != null) { |
| | | relationEntry.registerDeleteListener(adaptor); |
| | | if (configRepository.hasEntry(baseDN)) { |
| | | configRepository.registerDeleteListener(baseDN, adaptor); |
| | | } else { |
| | | // The relation entry does not exist yet so register a delayed |
| | | // add listener. |
| | | ConfigAddListener delayedListener = new DelayedConfigAddListener(baseDN, adaptor); |
| | | // The relation entry does not exist yet |
| | | // so register a delayed add listener. |
| | | ConfigAddListener delayedListener = new DelayedConfigAddListener(baseDN, adaptor, configRepository); |
| | | registerDelayedListener(baseDN, delayedListener); |
| | | } |
| | | } |
| | |
| | | import org.opends.server.admin.UndefinedDefaultBehaviorProvider; |
| | | import org.opends.server.admin.UnknownPropertyDefinitionException; |
| | | import org.opends.server.admin.DefinitionDecodingException.Reason; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.ConfigurationRepository; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.forgerock.opendj.admin.meta.RootCfgDefn; |
| | | import org.forgerock.opendj.admin.server.RootCfg; |
| | | import org.forgerock.opendj.ldap.Attribute; |
| | | import org.forgerock.opendj.ldap.AttributeDescription; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.util.DynamicConstants; |
| | | import org.slf4j.Logger; |
| | |
| | | |
| | | // Optional new configuration entry which does not yet exist in |
| | | // the configuration back-end. |
| | | private final ConfigEntry newConfigEntry; |
| | | private final Entry newConfigEntry; |
| | | |
| | | // The path of the managed object containing the next property. |
| | | private ManagedObjectPath<?, ?> nextPath = null; |
| | |
| | | private PropertyDefinition<T> nextProperty = null; |
| | | |
| | | // Private constructor. |
| | | private DefaultValueFinder(ConfigEntry newConfigEntry) { |
| | | private DefaultValueFinder(Entry newConfigEntry) { |
| | | this.newConfigEntry = newConfigEntry; |
| | | } |
| | | |
| | |
| | | |
| | | // Get an inherited property value. |
| | | @SuppressWarnings("unchecked") |
| | | private Collection<T> getInheritedProperty(ManagedObjectPath target, |
| | | private Collection<T> getInheritedProperty(ManagedObjectPath<?,?> target, |
| | | AbstractManagedObjectDefinition<?, ?> definition, String propertyName) |
| | | throws DefaultBehaviorException { |
| | | // First check that the requested type of managed object |
| | |
| | | try { |
| | | // Get the actual managed object definition. |
| | | DN dn = DNBuilder.create(target); |
| | | ConfigEntry configEntry; |
| | | if (newConfigEntry != null && newConfigEntry.getDN().equals(dn)) { |
| | | Entry configEntry; |
| | | if (newConfigEntry != null && newConfigEntry.getName().equals(dn)) { |
| | | configEntry = newConfigEntry; |
| | | } else { |
| | | configEntry = getManagedObjectConfigEntry(dn); |
| | |
| | | private class MyDefinitionResolver implements DefinitionResolver { |
| | | |
| | | // The config entry. |
| | | private final ConfigEntry entry; |
| | | private final Entry entry; |
| | | |
| | | // Private constructor. |
| | | private MyDefinitionResolver(ConfigEntry entry) { |
| | | private MyDefinitionResolver(Entry entry) { |
| | | this.entry = entry; |
| | | } |
| | | |
| | |
| | | */ |
| | | public boolean matches(AbstractManagedObjectDefinition<?, ?> d) { |
| | | String oc = LDAPProfile.getInstance().getObjectClass(d); |
| | | return entry.hasObjectClass(oc); |
| | | // TODO : use the schema to get object class and check it in the entry |
| | | // Commented because reject any config entry without proper schema loading |
| | | // Previous code was |
| | | // ObjectClass oc = DirectoryServer.getObjectClass(name.toLowerCase()); |
| | | // if (oc == null) { |
| | | // oc = DirectoryServer.getDefaultObjectClass(name); |
| | | // } |
| | | // return Entries.containsObjectClass(entry, oc); |
| | | return entry.containsAttribute("objectClass", oc); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | private static final Logger debugLogger = LoggerFactory.getLogger(ServerManagementContext.class); |
| | | |
| | | /** The singleton instance. **/ |
| | | private final static ServerManagementContext INSTANCE = new ServerManagementContext(); |
| | | |
| | | /** |
| | | * The root server managed object. |
| | | * The root server managed object, lazily initialized. |
| | | */ |
| | | private static final ServerManagedObject<RootCfg> ROOT = new ServerManagedObject<RootCfg>( |
| | | ManagedObjectPath.emptyPath(), RootCfgDefn.getInstance(), |
| | | Collections.<PropertyDefinition<?>, SortedSet<?>> emptyMap(), null); |
| | | private volatile ServerManagedObject<RootCfg> root; |
| | | |
| | | /** Repository of configuration entries */ |
| | | private final ConfigurationRepository configRepository; |
| | | |
| | | /** |
| | | * Get the single server-side management context. |
| | | * Creates a context from the provided configuration repository. |
| | | * |
| | | * @return Returns the single server-side management context. |
| | | * @param repository |
| | | * The repository of configuration entries. |
| | | */ |
| | | public static ServerManagementContext getInstance() { |
| | | return INSTANCE; |
| | | } |
| | | |
| | | // Private constructor. |
| | | private ServerManagementContext() { |
| | | // No implementation required. |
| | | ServerManagementContext(ConfigurationRepository repository) { |
| | | configRepository = repository; |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | // Get the configuration entry. |
| | | DN targetDN = DNBuilder.create(path); |
| | | ConfigEntry configEntry = getManagedObjectConfigEntry(targetDN); |
| | | Entry configEntry = getManagedObjectConfigEntry(targetDN); |
| | | try { |
| | | ServerManagedObject<? extends S> managedObject; |
| | | managedObject = decode(path, configEntry); |
| | |
| | | // Determine the exact type of managed object referenced by the |
| | | // path. |
| | | DN dn = DNBuilder.create(path); |
| | | ConfigEntry configEntry = getManagedObjectConfigEntry(dn); |
| | | Entry configEntry = getManagedObjectConfigEntry(dn); |
| | | |
| | | DefinitionResolver resolver = new MyDefinitionResolver(configEntry); |
| | | ManagedObjectDefinition<? extends C, ? extends S> managedObjDef; |
| | |
| | | * Get the root configuration manager associated with this management |
| | | * context. |
| | | * |
| | | * @return Returns the root configuration manager associated with this |
| | | * @return the root configuration manager associated with this |
| | | * management context. |
| | | */ |
| | | public RootCfg getRootConfiguration() { |
| | |
| | | * Get the root configuration server managed object associated with this |
| | | * management context. |
| | | * |
| | | * @return Returns the root configuration server managed object associated |
| | | * with this management context. |
| | | * @return the root configuration server managed object |
| | | */ |
| | | public ServerManagedObject<RootCfg> getRootConfigurationManagedObject() { |
| | | return ROOT; |
| | | // Use lazy initialisation because it needs a reference to this server context. |
| | | ServerManagedObject<RootCfg> rootObject = root; |
| | | if (rootObject == null) { |
| | | synchronized(this) { |
| | | rootObject = root; |
| | | if (rootObject == null) { |
| | | root = rootObject = new ServerManagedObject<RootCfg>(ManagedObjectPath.emptyPath(), |
| | | RootCfgDefn.getInstance(), Collections.<PropertyDefinition<?>, SortedSet<?>> emptyMap(), |
| | | null, this); |
| | | } |
| | | } |
| | | } |
| | | return rootObject; |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | // Get the target entry. |
| | | DN targetDN = DNBuilder.create(parent, relationDef); |
| | | ConfigEntry configEntry; |
| | | Set<DN> children; |
| | | try { |
| | | configEntry = DirectoryServer.getConfigEntry(targetDN); |
| | | children = configRepository.getChildren(targetDN); |
| | | } catch (ConfigException e) { |
| | | return new String[0]; |
| | | } |
| | | |
| | | if (configEntry == null) { |
| | | return new String[0]; |
| | | } |
| | | |
| | | // Retrieve the children. |
| | | Set<DN> children = configEntry.getChildren(); |
| | | List<String> names = new ArrayList<String>(children.size()); |
| | | for (DN child : children) { |
| | | // Assume that RDNs are single-valued and can be trimmed. |
| | |
| | | * be decoded. |
| | | */ |
| | | <C extends ConfigurationClient, S extends Configuration> ServerManagedObject<? extends S> decode( |
| | | ManagedObjectPath<C, S> path, ConfigEntry configEntry) throws DefinitionDecodingException, |
| | | ManagedObjectPath<C, S> path, Entry configEntry) throws DefinitionDecodingException, |
| | | ServerManagedObjectDecodingException { |
| | | return decode(path, configEntry, null); |
| | | } |
| | |
| | | * be decoded. |
| | | */ |
| | | <C extends ConfigurationClient, S extends Configuration> ServerManagedObject<? extends S> decode( |
| | | ManagedObjectPath<C, S> path, ConfigEntry configEntry, ConfigEntry newConfigEntry) |
| | | ManagedObjectPath<C, S> path, Entry configEntry, Entry newConfigEntry) |
| | | throws DefinitionDecodingException, ServerManagedObjectDecodingException { |
| | | // First determine the correct definition to use for the entry. |
| | | // This could either be the provided definition, or one of its |
| | |
| | | |
| | | // If there were no decoding problems then return the managed |
| | | // object, otherwise throw an operations exception. |
| | | ServerManagedObject<? extends S> mo = decodeAux(path, mod, properties, configEntry); |
| | | ServerManagedObject<? extends S> managedObject = decodeAux(path, mod, properties, configEntry.getName()); |
| | | if (exceptions.isEmpty()) { |
| | | return mo; |
| | | return managedObject; |
| | | } else { |
| | | throw new ServerManagedObjectDecodingException(mo, exceptions); |
| | | throw new ServerManagedObjectDecodingException(managedObject, exceptions); |
| | | } |
| | | } |
| | | |
| | | // Decode helper method required to avoid generics warning. |
| | | private <C extends ConfigurationClient, S extends Configuration> ServerManagedObject<S> decodeAux( |
| | | ManagedObjectPath<? super C, ? super S> path, ManagedObjectDefinition<C, S> d, |
| | | Map<PropertyDefinition<?>, SortedSet<?>> properties, ConfigEntry configEntry) { |
| | | Map<PropertyDefinition<?>, SortedSet<?>> properties, DN configDN) { |
| | | ManagedObjectPath<C, S> newPath = path.asSubType(d); |
| | | return new ServerManagedObject<S>(newPath, d, properties, configEntry); |
| | | return new ServerManagedObject<S>(newPath, d, properties, configDN, this); |
| | | } |
| | | |
| | | // Create a property using the provided string values. |
| | | private <T> SortedSet<T> decodeProperty(ManagedObjectPath<?, ?> path, PropertyDefinition<T> propertyDef, |
| | | Iterable<Attribute> attributes, ConfigEntry newConfigEntry) throws PropertyException { |
| | | Iterable<Attribute> attributes, Entry newConfigEntry) throws PropertyException { |
| | | PropertyException exception = null; |
| | | SortedSet<T> pvalues = new TreeSet<T>(propertyDef); |
| | | |
| | |
| | | |
| | | // Gets the attribute associated with a property from a ConfigEntry. |
| | | private Iterable<Attribute> getAttribute(ManagedObjectDefinition<?, ?> d, PropertyDefinition<?> pd, |
| | | ConfigEntry configEntry) { |
| | | Entry configEntry) { |
| | | // TODO: we create a default attribute type if it is |
| | | // undefined. We should log a warning here if this is the case |
| | | // since the attribute should have been defined. |
| | | String attrID = LDAPProfile.getInstance().getAttributeName(d, pd); |
| | | AttributeType type = DirectoryServer.getAttributeType(attrID, true); |
| | | return configEntry.getEntry().getAllAttributes(AttributeDescription.create(type)); |
| | | return configEntry.getAllAttributes(AttributeDescription.create(type)); |
| | | } |
| | | |
| | | // Get the default values for the specified property. |
| | | private <T> Collection<T> getDefaultValues(ManagedObjectPath<?, ?> p, PropertyDefinition<T> pd, |
| | | ConfigEntry newConfigEntry) throws DefaultBehaviorException { |
| | | Entry newConfigEntry) throws DefaultBehaviorException { |
| | | DefaultValueFinder<T> v = new DefaultValueFinder<T>(newConfigEntry); |
| | | return v.find(p, pd); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a configuration entry corresponding to the provided DN. |
| | | * |
| | | * @param dn |
| | | * DN of the configuration entry. |
| | | * @return the configuration entry |
| | | * @throws ConfigException |
| | | * If a problem occurs. |
| | | */ |
| | | public Entry getConfigEntry(DN dn) throws ConfigException { |
| | | return configRepository.getEntry(dn); |
| | | } |
| | | |
| | | /** |
| | | * Returns the repository containing all configuration entries. |
| | | * |
| | | * @return the repository |
| | | */ |
| | | public ConfigurationRepository getConfigRepository() { |
| | | return configRepository; |
| | | } |
| | | |
| | | // Gets a config entry required for a managed object and throws a |
| | | // config exception on failure. |
| | | private ConfigEntry getManagedObjectConfigEntry(DN dn) throws ConfigException { |
| | | ConfigEntry configEntry; |
| | | private Entry getManagedObjectConfigEntry(DN dn) throws ConfigException { |
| | | Entry configEntry; |
| | | try { |
| | | configEntry = DirectoryServer.getConfigEntry(dn); |
| | | configEntry = configRepository.getEntry(dn); |
| | | } catch (ConfigException e) { |
| | | debugLogger.trace("Unable to perform post add", e); |
| | | |
| | |
| | | package org.opends.server.api; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | |
| | | /** |
| | |
| | | * @return {@code true} if the proposed entry contains an acceptable |
| | | * configuration, or {@code false} if it does not. |
| | | */ |
| | | public boolean configAddIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason); |
| | | public boolean configAddIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason); |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration based on the provided added entry. |
| | |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry); |
| | | public ConfigChangeResult applyConfigurationAdd(Entry configEntry); |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.api; |
| | | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * This interface defines the methods that a Directory Server component should |
| | |
| | | * @return {@code true} if the proposed entry contains an acceptable |
| | | * configuration, or {@code false} if it does not. |
| | | */ |
| | | public boolean configChangeIsAcceptable(ConfigEntry configEntry, LocalizableMessageBuilder unacceptableReason); |
| | | public boolean configChangeIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason); |
| | | |
| | | /** |
| | | * Attempts to apply a new configuration to this Directory Server component |
| | |
| | | * @return Information about the result of processing the configuration |
| | | * change. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry); |
| | | public ConfigChangeResult applyConfigurationChange(Entry configEntry); |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.api; |
| | | |
| | | |
| | | |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | |
| | | /** |
| | | * This interface defines the methods that a Directory Server |
| | | * component should implement if it wishes to be able to receive |
| | | * notification if entries below a configuration entry are removed. |
| | | * This interface defines the methods that a Directory Server component should |
| | | * implement if it wishes to be able to receive notification if entries below a |
| | | * configuration entry are removed. |
| | | */ |
| | | public interface ConfigDeleteListener |
| | | { |
| | | /** |
| | | * 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} if the proposed entry may be removed from |
| | | * the configuration, or {@code false} if not. |
| | | */ |
| | | public boolean configDeleteIsAcceptable(ConfigEntry configEntry, |
| | | LocalizableMessageBuilder unacceptableReason); |
| | | public interface ConfigDeleteListener { |
| | | /** |
| | | * 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} if the proposed entry may be removed from the |
| | | * configuration, or {@code false} if not. |
| | | */ |
| | | public boolean configDeleteIsAcceptable(Entry configEntry, LocalizableMessageBuilder unacceptableReason); |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete( |
| | | ConfigEntry configEntry); |
| | | /** |
| | | * 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. |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(Entry configEntry); |
| | | } |
| | | |
| | |
| | | */ |
| | | package org.opends.server.config; |
| | | |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | |
| | | /** |
| | | * Provides the configuration elements. |
| | | * Provides configuration entries and listener registration on the entries. |
| | | */ |
| | | public interface ConfigurationRepository { |
| | | |
| | | /** |
| | | * Returns the set of children of the provided entry. |
| | | * Returns the set of DNs of children of the entry corresponding to the |
| | | * provided DN. . |
| | | * |
| | | * @param entry |
| | | * The configuration entry. |
| | | * @return the set of children of the entry |
| | | * @param dn |
| | | * DN of a configuration entry. |
| | | * @return the set of DN of children of the corresponding entry |
| | | * @throws ConfigException |
| | | * If a problem occurs during retrieval. |
| | | */ |
| | | Set<DN> getChildren(Entry entry); |
| | | Set<DN> getChildren(DN dn) throws ConfigException; |
| | | |
| | | /** |
| | | * Returns the configuration entry for the provided DN. |
| | | * |
| | | * @param dn |
| | | * DN of the configuration entry |
| | | * @return the config entry |
| | | * @throws ConfigException |
| | | * If a problem occurs while trying to retrieve the requested |
| | | * entry. |
| | | */ |
| | | Entry getEntry(DN dn) throws ConfigException; |
| | | |
| | | /** |
| | | * Checks if the provided DN corresponds to a configuration entry. |
| | | * |
| | | * @param dn |
| | | * DN of the configuration entry |
| | | * @return {@code true} if and only if there is a configuration entry with |
| | | * this DN |
| | | * @throws ConfigException |
| | | * If a problem occurs. |
| | | */ |
| | | boolean hasEntry(DN dn) throws ConfigException; |
| | | |
| | | /** |
| | | * Registers the provided add listener so that it will be notified if any |
| | | * new entries are added immediately below the entry corresponding to the |
| | | * provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @param listener |
| | | * The add listener that should be registered. |
| | | */ |
| | | public void registerAddListener(DN dn, ConfigAddListener listener); |
| | | |
| | | /** |
| | | * Registers the provided delete listener so that it will be notified if any |
| | | * entries are deleted immediately below the entry corresponding to the |
| | | * provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @param listener |
| | | * The delete listener that should be registered. |
| | | */ |
| | | public void registerDeleteListener(DN dn, ConfigDeleteListener listener); |
| | | |
| | | /** |
| | | * Registers the provided change listener so that it will be notified of any |
| | | * changes to the entry corrresponding to provided DN. No check will be made |
| | | * to determine whether the provided listener is already registered. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @param listener |
| | | * The change listener that should be registered. |
| | | */ |
| | | public void registerChangeListener(DN dn, ConfigChangeListener listener); |
| | | |
| | | /** |
| | | * Deregisters the provided add listener so that it will no longer be |
| | | * notified if any new entries are added immediately below the entry |
| | | * corresponding to the provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @param listener |
| | | * The add listener that should be deregistered. |
| | | */ |
| | | public void deregisterAddListener(DN dn, ConfigAddListener listener); |
| | | |
| | | /** |
| | | * Deregisters the provided delete listener so that it will no longer be |
| | | * notified if any entries are deleted immediately below the entry |
| | | * corresponding to the provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @param listener |
| | | * The delete listener that should be deregistered. |
| | | */ |
| | | public void deregisterDeleteListener(DN dn, ConfigDeleteListener listener); |
| | | |
| | | /** |
| | | * Attempts to deregister the provided change listener with the provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @param listener |
| | | * The change listener to deregister with this DN. |
| | | * @return <CODE>true</CODE> if the specified listener was deregistered, or |
| | | * <CODE>false</CODE> if it was not. |
| | | */ |
| | | public boolean deregisterChangeListener(DN dn, ConfigChangeListener listener); |
| | | |
| | | /** |
| | | * Retrieves the add listeners that have been registered with the provided |
| | | * DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @return The list of add listeners. |
| | | */ |
| | | public List<ConfigAddListener> getAddListeners(DN dn); |
| | | |
| | | /** |
| | | * Retrieves the delete listeners that have been registered with the |
| | | * provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @return The list of delete listeners. |
| | | */ |
| | | public List<ConfigDeleteListener> getDeleteListeners(DN dn); |
| | | |
| | | /** |
| | | * Retrieves the change listeners that have been registered with the |
| | | * provided DN. |
| | | * |
| | | * @param dn |
| | | * The DN of the configuration entry. |
| | | * @return The list of change listeners. |
| | | */ |
| | | public List<ConfigChangeListener> getChangeListeners(DN dn); |
| | | |
| | | } |
| | |
| | | */ |
| | | package org.opends.server.core; |
| | | |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.forgerock.opendj.ldap.schema.ObjectClass; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | import org.forgerock.opendj.ldap.schema.UnknownSchemaElementException; |
| | | import org.opends.server.config.ConfigEntry; |
| | | import org.opends.server.config.ConfigException; |
| | | |
| | | /** |
| | | * TODO : this is a stub, with some default implementations for some methods, |
| | |
| | | return getObjectClass(name); |
| | | } |
| | | |
| | | public static ConfigEntry getConfigEntry(DN dn) throws ConfigException { |
| | | throw new RuntimeException("Not implemented"); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import org.forgerock.opendj.admin.meta.RootCfgDefn; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.opends.server.admin.AbstractManagedObjectDefinition; |
| | | import org.opends.server.admin.Configuration; |
| | | import org.opends.server.admin.ConfigurationClient; |
| | | import org.opends.server.admin.DefinitionDecodingException; |
| | | import org.opends.server.admin.LDAPProfile; |
| | | import org.opends.server.admin.ManagedObjectPath; |
| | | import org.opends.server.admin.RelationDefinition; |
| | | import org.opends.server.admin.SingletonRelationDefinition; |
| | | import org.opends.server.config.ConfigException; |
| | | |
| | | /** |
| | | * This class defines some utility functions which can be used by test cases |
| | | * which interact with the admin framework. |
| | | */ |
| | | public final class AdminTestCaseUtils { |
| | | |
| | | // The relation name which will be used for dummy configurations. A |
| | | // deliberately obfuscated name is chosen to avoid clashes. |
| | | private static final String DUMMY_TEST_RELATION = "*dummy*test*relation*"; |
| | | |
| | | // Indicates if the dummy relation profile has been registered. |
| | | private static boolean isProfileRegistered = false; |
| | | |
| | | // Prevent instantiation. |
| | | private AdminTestCaseUtils() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * Decodes a configuration entry into the required type of server |
| | | * configuration. |
| | | * |
| | | * @param <S> |
| | | * The type of server configuration to be decoded. |
| | | * @param definition |
| | | * The required definition of the required managed object. |
| | | * @param entry |
| | | * An entry containing the configuration to be decoded. |
| | | * @return Returns the new server-side configuration. |
| | | * @throws ConfigException |
| | | * If the entry could not be decoded. |
| | | */ |
| | | public static <S extends Configuration> S getConfiguration(ServerManagementContext context, |
| | | AbstractManagedObjectDefinition<?, S> definition, Entry entry) throws ConfigException { |
| | | try { |
| | | ServerManagedObject<? extends S> mo = context.decode(getPath(definition), entry); |
| | | |
| | | // Ensure constraints are satisfied. |
| | | mo.ensureIsUsable(); |
| | | |
| | | return mo.getConfiguration(); |
| | | } catch (DefinitionDecodingException e) { |
| | | throw ConfigExceptionFactory.getInstance().createDecodingExceptionAdaptor(entry.getName(), e); |
| | | } catch (ServerManagedObjectDecodingException e) { |
| | | throw ConfigExceptionFactory.getInstance().createDecodingExceptionAdaptor(e); |
| | | } catch (ConstraintViolationException e) { |
| | | throw ConfigExceptionFactory.getInstance().createDecodingExceptionAdaptor(e); |
| | | } |
| | | } |
| | | |
| | | // Construct a dummy path. |
| | | private synchronized static <C extends ConfigurationClient, S extends Configuration> ManagedObjectPath<C, S> getPath( |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | if (!isProfileRegistered) { |
| | | LDAPProfile.Wrapper profile = new LDAPProfile.Wrapper() { |
| | | |
| | | @Override |
| | | public String getRelationRDNSequence(RelationDefinition<?, ?> r) { |
| | | if (r.getName().equals(DUMMY_TEST_RELATION)) { |
| | | return "cn=dummy configuration,cn=config"; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | }; |
| | | |
| | | LDAPProfile.getInstance().pushWrapper(profile); |
| | | isProfileRegistered = true; |
| | | } |
| | | |
| | | SingletonRelationDefinition.Builder<C, S> builder = new SingletonRelationDefinition.Builder<C, S>( |
| | | RootCfgDefn.getInstance(), DUMMY_TEST_RELATION, d); |
| | | ManagedObjectPath<?, ?> root = ManagedObjectPath.emptyPath(); |
| | | return root.child(builder.getInstance()); |
| | | |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2007-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2013 ForgeRock AS |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.SortedSet; |
| | | import java.util.TreeSet; |
| | | |
| | | import javax.naming.ldap.LdapName; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.admin.client.ConnectionHandlerCfgClient; |
| | | import org.forgerock.opendj.admin.client.LDAPConnectionHandlerCfgClient; |
| | | import org.forgerock.opendj.admin.client.RootCfgClient; |
| | | import org.forgerock.opendj.admin.meta.LDAPConnectionHandlerCfgDefn; |
| | | import org.forgerock.opendj.admin.server.ConnectionHandlerCfg; |
| | | import org.forgerock.opendj.admin.server.RootCfg; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.TestCaseUtils; |
| | | import org.opends.server.admin.AdminTestCase; |
| | | import org.opends.server.admin.AdministratorAction; |
| | | import org.opends.server.admin.AggregationPropertyDefinition; |
| | | import org.opends.server.admin.IllegalPropertyValueStringException; |
| | | import org.opends.server.admin.ManagedObjectNotFoundException; |
| | | import org.opends.server.admin.PropertyException; |
| | | import org.opends.server.admin.PropertyOption; |
| | | import org.opends.server.admin.TestCfg; |
| | | import org.opends.server.admin.TestChildCfg; |
| | | import org.opends.server.admin.TestChildCfgDefn; |
| | | import org.opends.server.admin.TestParentCfg; |
| | | import org.opends.server.admin.UndefinedDefaultBehaviorProvider; |
| | | import org.opends.server.admin.client.OperationRejectedException; |
| | | import org.opends.server.admin.condition.Conditions; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.testng.Assert; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * Test cases for aggregations on the server-side. |
| | | */ |
| | | @Test(singleThreaded = true) |
| | | public final class AggregationServerTest extends AdminTestCase { |
| | | |
| | | /** |
| | | * Dummy change listener for triggering change constraint call-backs. |
| | | */ |
| | | private static final class DummyChangeListener implements ConfigurationChangeListener<TestChildCfg> { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationChange(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isConfigurationChangeAcceptable(TestChildCfg configuration, List<LocalizableMessage> unacceptableReasons) { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Dummy delete listener for triggering delete constraint call-backs. |
| | | */ |
| | | private static final class DummyDeleteListener implements ConfigurationDeleteListener<TestChildCfg> { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public ConfigChangeResult applyConfigurationDelete(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isConfigurationDeleteAcceptable(TestChildCfg configuration, List<LocalizableMessage> unacceptableReasons) { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | private static final String TEST_CHILD_7_DN = "cn=test child 7,cn=test children,cn=test parent 1,cn=test parents,cn=config"; |
| | | |
| | | private static final String TEST_CHILD_6_DN = "cn=test child 6,cn=test children,cn=test parent 1,cn=test parents,cn=config"; |
| | | |
| | | /** The name of the test connection handler. */ |
| | | private static final String TEST_CONNECTION_HANDLER_NAME = "Test Connection Handler"; |
| | | |
| | | /** Test child 1 LDIF. */ |
| | | private static final String[] TEST_CHILD_1 = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 1", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real" }; |
| | | |
| | | /** Test child 2 LDIF. */ |
| | | private static final String[] TEST_CHILD_2 = new String[] { |
| | | "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 2", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config" }; |
| | | |
| | | /** Test child 3 LDIF (invalid reference). */ |
| | | private static final String[] TEST_CHILD_3 = new String[] { |
| | | "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 3", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=bad rdn, cn=config" }; |
| | | |
| | | /** Test child 4 LDIF. */ |
| | | private static final String[] TEST_CHILD_4 = new String[] { |
| | | "dn: cn=test child 4,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 4", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config", |
| | | "ds-cfg-rotation-policy: cn=LDAPS Connection Handler, cn=connection handlers, cn=config" }; |
| | | |
| | | /** Test child 5 LDIF. */ |
| | | private static final String[] TEST_CHILD_5 = new String[] { |
| | | "dn: cn=test child 5,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 5", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-rotation-policy: cn=BAD Connection Handler 1, cn=connection handlers, cn=config", |
| | | "ds-cfg-rotation-policy: cn=BAD Connection Handler 2, cn=connection handlers, cn=config", |
| | | "ds-cfg-rotation-policy: cn=LDAP Connection Handler, cn=connection handlers, cn=config" }; |
| | | |
| | | /** Test child 6 LDIF. */ |
| | | private static final String[] TEST_CHILD_6 = new String[] { |
| | | "dn: cn=test child 6,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 6", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-rotation-policy: cn=" + TEST_CONNECTION_HANDLER_NAME + ", cn=connection handlers, cn=config" }; |
| | | |
| | | /** Test child 7 LDIF. */ |
| | | private static final String[] TEST_CHILD_7 = new String[] { |
| | | "dn: cn=test child 7,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 7", "ds-cfg-enabled: false", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-rotation-policy: cn=" + TEST_CONNECTION_HANDLER_NAME + ", cn=connection handlers, cn=config" }; |
| | | |
| | | /** Test LDIF. */ |
| | | private static final String[] TEST_LDIF = new String[] { |
| | | // Base entries. |
| | | "dn: cn=test parents,cn=config", |
| | | "objectclass: top", |
| | | "objectclass: ds-cfg-branch", |
| | | "cn: test parents", |
| | | "", |
| | | // Parent 1. |
| | | "dn: cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-parent-dummy", "cn: test parent 1", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", "", |
| | | // Child base entries. |
| | | "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-branch", "cn: test children", "" }; |
| | | |
| | | /** |
| | | * The saved test child configuration "aggregation-property" property |
| | | * definition. |
| | | */ |
| | | private AggregationPropertyDefinition<ConnectionHandlerCfgClient, ConnectionHandlerCfg> |
| | | aggregationPropertyDefinitionDefault = null; |
| | | |
| | | /** |
| | | * An aggregation where the target must be enabled if the source is enabled. |
| | | */ |
| | | private AggregationPropertyDefinition<ConnectionHandlerCfgClient, ConnectionHandlerCfg> |
| | | aggregationPropertyDefinitionTargetAndSourceMustBeEnabled = null; |
| | | |
| | | /** An aggregation where the target must be enabled. */ |
| | | private AggregationPropertyDefinition<ConnectionHandlerCfgClient, ConnectionHandlerCfg> |
| | | aggregationPropertyDefinitionTargetMustBeEnabled = null; |
| | | |
| | | /** |
| | | * Sets up tests |
| | | * |
| | | * @throws Exception |
| | | * If the server could not be initialized. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | TestCfg.setUp(); |
| | | |
| | | // Add test managed objects. |
| | | TestCaseUtils.addEntries(TEST_LDIF); |
| | | |
| | | // Save the aggregation property definition so that it can be |
| | | // replaced and restored later. |
| | | aggregationPropertyDefinitionDefault = TestChildCfgDefn.getInstance() |
| | | .getAggregationPropertyPropertyDefinition(); |
| | | |
| | | // Create the two test aggregation properties. |
| | | AggregationPropertyDefinition.Builder<ConnectionHandlerCfgClient, ConnectionHandlerCfg> builder; |
| | | TestChildCfgDefn d = TestChildCfgDefn.getInstance(); |
| | | builder = AggregationPropertyDefinition.createBuilder(d, "aggregation-property"); |
| | | builder.setOption(PropertyOption.MULTI_VALUED); |
| | | builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, d, |
| | | "aggregation-property")); |
| | | builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>()); |
| | | builder.setParentPath("/"); |
| | | builder.setRelationDefinition("connection-handler"); |
| | | builder.setTargetIsEnabledCondition(Conditions.contains("enabled", "true")); |
| | | aggregationPropertyDefinitionTargetMustBeEnabled = builder.getInstance(); |
| | | TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled); |
| | | |
| | | builder = AggregationPropertyDefinition.createBuilder(d, "aggregation-property"); |
| | | builder.setOption(PropertyOption.MULTI_VALUED); |
| | | builder.setAdministratorAction(new AdministratorAction(AdministratorAction.Type.NONE, d, |
| | | "aggregation-property")); |
| | | builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>()); |
| | | builder.setParentPath("/"); |
| | | builder.setRelationDefinition("connection-handler"); |
| | | builder.setTargetIsEnabledCondition(Conditions.contains("enabled", "true")); |
| | | builder.setTargetNeedsEnablingCondition(Conditions.contains("mandatory-boolean-property", "true")); |
| | | aggregationPropertyDefinitionTargetAndSourceMustBeEnabled = builder.getInstance(); |
| | | TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled); |
| | | } |
| | | |
| | | /** |
| | | * Tears down test environment. |
| | | * |
| | | * @throws Exception |
| | | * If the test entries could not be removed. |
| | | */ |
| | | @AfterClass |
| | | public void tearDown() throws Exception { |
| | | TestCfg.cleanup(); |
| | | |
| | | // Restore the test child aggregation definition. |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | |
| | | // Remove test entries. |
| | | deleteSubtree("cn=test parents,cn=config"); |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation is rejected when the LDAP DN contains a valid RDN |
| | | * but an invalid parent DN. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationBadBaseDN() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_3); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 3"); |
| | | Assert.fail("Unexpectedly added test child 3 when it had a bad aggregation value"); |
| | | } catch (ConfigException e) { |
| | | // Check that we have a decoding exception as the cause and |
| | | // there was only one cause the illegal property value. |
| | | Throwable cause = e.getCause(); |
| | | if (cause instanceof ServerManagedObjectDecodingException) { |
| | | ServerManagedObjectDecodingException de = (ServerManagedObjectDecodingException) cause; |
| | | |
| | | Collection<PropertyException> causes = de.getCauses(); |
| | | Assert.assertEquals(causes.size(), 1); |
| | | |
| | | cause = causes.iterator().next(); |
| | | if (cause instanceof IllegalPropertyValueStringException) { |
| | | IllegalPropertyValueStringException pe = (IllegalPropertyValueStringException) cause; |
| | | Assert.assertEquals(pe.getPropertyDefinition(), TestChildCfgDefn.getInstance() |
| | | .getAggregationPropertyPropertyDefinition()); |
| | | Assert.assertEquals(pe.getIllegalValueString(), |
| | | "cn=LDAP Connection Handler, cn=bad rdn, cn=config"); |
| | | } else { |
| | | // Got an unexpected cause. |
| | | throw e; |
| | | } |
| | | } else { |
| | | // Got an unexpected cause. |
| | | throw e; |
| | | } |
| | | } finally { |
| | | deleteSubtree("cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation is rejected by a constraint violation when the DN |
| | | * values are dangling. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationDanglingReference() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_5); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 5"); |
| | | Assert.fail("Unexpectedly added test child 5 when it had a dangling reference"); |
| | | } catch (ConfigException e) { |
| | | // Check that we have a constraint violation as the cause. |
| | | Throwable cause = e.getCause(); |
| | | if (cause instanceof ConstraintViolationException) { |
| | | ConstraintViolationException cve = (ConstraintViolationException) cause; |
| | | Collection<LocalizableMessage> causes = cve.getMessages(); |
| | | Assert.assertEquals(causes.size(), 2); |
| | | } else { |
| | | // Got an unexpected cause. |
| | | throw e; |
| | | } |
| | | } finally { |
| | | deleteSubtree("cn=test child 5,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation is rejected by a constraint violation when an |
| | | * enabled component references a disabled component and the referenced |
| | | * component must always be enabled. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationDisabledReference1() throws Exception { |
| | | // Add the entry and the connection handler. |
| | | TestCaseUtils.addEntry(TEST_CHILD_6); |
| | | try { |
| | | createConnectionHandler(false); |
| | | } catch (Exception e) { |
| | | deleteSubtree(TEST_CHILD_6_DN); |
| | | throw e; |
| | | } |
| | | |
| | | // Register the temporary aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 6"); |
| | | Assert.fail("Unexpectedly added test child 6 when it had a disabled reference"); |
| | | } catch (ConfigException e) { |
| | | // Check that we have a constraint violation as the cause. |
| | | Throwable cause = e.getCause(); |
| | | if (cause instanceof ConstraintViolationException) { |
| | | ConstraintViolationException cve = (ConstraintViolationException) cause; |
| | | Collection<LocalizableMessage> causes = cve.getMessages(); |
| | | Assert.assertEquals(causes.size(), 1); |
| | | } else { |
| | | // Got an unexpected cause. |
| | | throw e; |
| | | } |
| | | } finally { |
| | | // Put back the default aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | |
| | | try { |
| | | deleteSubtree(TEST_CHILD_6_DN); |
| | | } finally { |
| | | deleteConnectionHandler(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation is rejected by a constraint violation when a |
| | | * disabled component references a disabled component and the referenced |
| | | * component must always be enabled. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationDisabledReference2() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_7); |
| | | try { |
| | | createConnectionHandler(false); |
| | | } catch (Exception e) { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | throw e; |
| | | } |
| | | |
| | | // Register the temporary aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 7"); |
| | | Assert.fail("Unexpectedly added test child 7 when it had a disabled reference"); |
| | | } catch (ConfigException e) { |
| | | // Check that we have a constraint violation as the cause. |
| | | Throwable cause = e.getCause(); |
| | | if (cause instanceof ConstraintViolationException) { |
| | | ConstraintViolationException cve = (ConstraintViolationException) cause; |
| | | Collection<LocalizableMessage> causes = cve.getMessages(); |
| | | Assert.assertEquals(causes.size(), 1); |
| | | } else { |
| | | // Got an unexpected cause. |
| | | throw e; |
| | | } |
| | | } finally { |
| | | // Put back the default aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | |
| | | try { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | } finally { |
| | | deleteConnectionHandler(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation is rejected by a constraint violation when an |
| | | * enabled component references a disabled component and the referenced |
| | | * component must always be enabled when the referencing component is |
| | | * enabled. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationDisabledReference3() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_6); |
| | | try { |
| | | createConnectionHandler(false); |
| | | } catch (Exception e) { |
| | | deleteSubtree(TEST_CHILD_6_DN); |
| | | throw e; |
| | | } |
| | | |
| | | // Register the temporary aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled.getSourceConstraint()); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 6"); |
| | | Assert.fail("Unexpectedly added test child 6 when it had a disabled reference"); |
| | | } catch (ConfigException e) { |
| | | // Check that we have a constraint violation as the cause. |
| | | Throwable cause = e.getCause(); |
| | | if (cause instanceof ConstraintViolationException) { |
| | | ConstraintViolationException cve = (ConstraintViolationException) cause; |
| | | Collection<LocalizableMessage> causes = cve.getMessages(); |
| | | Assert.assertEquals(causes.size(), 1); |
| | | } else { |
| | | // Got an unexpected cause. |
| | | throw e; |
| | | } |
| | | } finally { |
| | | // Put back the default aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | |
| | | try { |
| | | deleteSubtree(TEST_CHILD_6_DN); |
| | | } finally { |
| | | deleteConnectionHandler(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation is allowed when a disabled component references a |
| | | * disabled component and the referenced component must always be enabled |
| | | * when the referencing component is enabled. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationDisabledReference4() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_7); |
| | | try { |
| | | createConnectionHandler(false); |
| | | } catch (Exception e) { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | throw e; |
| | | } |
| | | |
| | | // Register the temporary aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled.getSourceConstraint()); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 7"); |
| | | } finally { |
| | | // Put back the default aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | |
| | | try { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | } finally { |
| | | deleteConnectionHandler(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation contains no values when it contains does not |
| | | * contain any DN attribute values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationEmpty() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | assertChild1(parent.getTestChild("test child 1")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation contains multiple valid values when it contains a |
| | | * multiple valid DN attribute values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationMultipleValues() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_4); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | assertChild4(parent.getTestChild("test child 4")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 4,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that aggregation contains single valid value when it contains a |
| | | * single valid DN attribute values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAggregationSingle() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_2); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | assertChild2(parent.getTestChild("test child 2")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that it is impossible to delete a referenced component when the |
| | | * referenced component must always exist regardless of whether the |
| | | * referencing component is enabled or not. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testCannotDeleteReferencedComponent() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_7); |
| | | try { |
| | | createConnectionHandler(true); |
| | | } catch (Exception e) { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | throw e; |
| | | } |
| | | |
| | | // Register the temporary aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | |
| | | ConfigurationDeleteListener<TestChildCfg> dl = new DummyDeleteListener(); |
| | | ConfigurationChangeListener<TestChildCfg> cl = new DummyChangeListener(); |
| | | try { |
| | | // Retrieve the parent and child managed objects and register |
| | | // delete and change listeners respectively in order to trigger |
| | | // the constraint call-backs. |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.addTestChildDeleteListener(dl); |
| | | |
| | | TestChildCfg child = parent.getTestChild("test child 7"); |
| | | child.addChangeListener(cl); |
| | | |
| | | // Now attempt to delete the referenced connection handler. |
| | | // This should fail. |
| | | try { |
| | | deleteConnectionHandler(); |
| | | Assert.fail("Successfully deleted a referenced component"); |
| | | } catch (OperationRejectedException e) { |
| | | // This is the expected exception - do nothing. |
| | | } |
| | | } finally { |
| | | try { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | } finally { |
| | | try { |
| | | deleteConnectionHandler(); |
| | | } catch (ManagedObjectNotFoundException e) { |
| | | // Ignore as it may have been deleted already. |
| | | } finally { |
| | | // Remove the temporary delete listener. |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.removeTestChildDeleteListener(dl); |
| | | |
| | | // Put back the default aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that it is impossible to disable a referenced component when the |
| | | * referenced component must always be enabled regardless of whether the |
| | | * referencing component is enabled or not. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testCannotDisableReferencedComponent() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_7); |
| | | try { |
| | | createConnectionHandler(true); |
| | | } catch (Exception e) { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | throw e; |
| | | } |
| | | |
| | | // Register the temporary aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | |
| | | ConfigurationDeleteListener<TestChildCfg> dl = new DummyDeleteListener(); |
| | | ConfigurationChangeListener<TestChildCfg> cl = new DummyChangeListener(); |
| | | try { |
| | | // Retrieve the parent and child managed objects and register |
| | | // delete and change listeners respectively in order to trigger |
| | | // the constraint call-backs. |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.addTestChildDeleteListener(dl); |
| | | |
| | | TestChildCfg child = parent.getTestChild("test child 7"); |
| | | child.addChangeListener(cl); |
| | | |
| | | // Now attempt to disable the referenced connection handler. |
| | | // This should fail. |
| | | try { |
| | | RootCfgClient root = TestCaseUtils.getRootConfiguration(); |
| | | ConnectionHandlerCfgClient client = root.getConnectionHandler(TEST_CONNECTION_HANDLER_NAME); |
| | | client.setEnabled(false); |
| | | client.commit(); |
| | | Assert.fail("Successfully disabled a referenced component"); |
| | | } catch (OperationRejectedException e) { |
| | | // This is the expected exception - do nothing. |
| | | } |
| | | } finally { |
| | | try { |
| | | deleteSubtree(TEST_CHILD_7_DN); |
| | | } finally { |
| | | try { |
| | | deleteConnectionHandler(); |
| | | } finally { |
| | | // Remove the temporary delete listener. |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.removeTestChildDeleteListener(dl); |
| | | |
| | | // Put back the default aggregation definition. |
| | | TestCfg.removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled.getSourceConstraint()); |
| | | TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault); |
| | | TestCfg.addConstraint(aggregationPropertyDefinitionDefault.getSourceConstraint()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** Assert that the values of child 1 are correct. */ |
| | | private void assertChild1(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertSetEquals(child.getAggregationProperty(), new String[0]); |
| | | } |
| | | |
| | | /** Assert that the values of child 2 are correct. */ |
| | | private void assertChild2(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | |
| | | // Test normalization. |
| | | assertSetEquals(child.getAggregationProperty(), "LDAP Connection Handler"); |
| | | assertSetEquals(child.getAggregationProperty(), " LDAP Connection Handler "); |
| | | assertSetEquals(child.getAggregationProperty(), " ldap connection HANDLER "); |
| | | } |
| | | |
| | | /** Assert that the values of child 4 are correct. */ |
| | | private void assertChild4(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertSetEquals(child.getAggregationProperty(), "LDAPS Connection Handler", "LDAP Connection Handler"); |
| | | } |
| | | |
| | | /** Asserts that the actual set of DNs contains the expected values. */ |
| | | private void assertSetEquals(SortedSet<String> actual, String... expected) { |
| | | SortedSet<String> values = new TreeSet<String>(TestChildCfgDefn.getInstance() |
| | | .getAggregationPropertyPropertyDefinition()); |
| | | if (expected != null) { |
| | | for (String value : expected) { |
| | | values.add(value); |
| | | } |
| | | } |
| | | Assert.assertEquals((Object) actual, (Object) values); |
| | | } |
| | | |
| | | /** Creates a test connection handler for testing. */ |
| | | private void createConnectionHandler(boolean enabled) throws Exception { |
| | | RootCfgClient root = TestCaseUtils.getRootConfiguration(); |
| | | LDAPConnectionHandlerCfgClient client = root.createConnectionHandler( |
| | | LDAPConnectionHandlerCfgDefn.getInstance(), TEST_CONNECTION_HANDLER_NAME, null); |
| | | client.setEnabled(enabled); |
| | | client.setListenPort(1000); |
| | | client.commit(); |
| | | } |
| | | |
| | | /** Deletes the test connection handler after testing. */ |
| | | private void deleteConnectionHandler() throws Exception { |
| | | RootCfgClient root = TestCaseUtils.getRootConfiguration(); |
| | | root.removeConnectionHandler(TEST_CONNECTION_HANDLER_NAME); |
| | | } |
| | | |
| | | /** Gets the named parent configuration. */ |
| | | private TestParentCfg getParent(String name) throws IllegalArgumentException, ConfigException { |
| | | ServerManagedObject<RootCfg> root = serverContext.getRootConfigurationManagedObject(); |
| | | return root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name).getConfiguration(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import java.util.List; |
| | | |
| | | import javax.naming.OperationNotSupportedException; |
| | | import javax.naming.ldap.LdapName; |
| | | |
| | | import org.opends.server.admin.AdminTestCase; |
| | | import org.opends.server.admin.TestCfg; |
| | | import org.opends.server.admin.TestChildCfg; |
| | | import org.opends.server.admin.TestChildCfgDefn; |
| | | import org.opends.server.admin.TestParentCfg; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.testng.Assert; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * Test cases for constraints on the server-side. |
| | | */ |
| | | public final class ConstraintTest extends AdminTestCase { |
| | | |
| | | // Child DN. |
| | | private static final String TEST_CHILD_1_DN = "cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"; |
| | | |
| | | /** |
| | | * A test child add listener. |
| | | */ |
| | | private static class AddListener implements ConfigurationAddListener<TestChildCfg> { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationAddAcceptable(TestChildCfg configuration, List<Message> unacceptableReasons) { |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * A test child delete listener. |
| | | */ |
| | | private static class DeleteListener implements ConfigurationDeleteListener<TestChildCfg> { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationDeleteAcceptable(TestChildCfg configuration, List<Message> unacceptableReasons) { |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * A test child change listener. |
| | | */ |
| | | private static class ChangeListener implements ConfigurationChangeListener<TestChildCfg> { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable(TestChildCfg configuration, List<Message> unacceptableReasons) { |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | // Test child 1 LDIF. |
| | | private static final String[] TEST_CHILD_1 = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 1", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real" }; |
| | | |
| | | // Test LDIF. |
| | | private static final String[] TEST_LDIF = new String[] { |
| | | // Base entries. |
| | | "dn: cn=test parents,cn=config", |
| | | "objectclass: top", |
| | | "objectclass: ds-cfg-branch", |
| | | "cn: test parents", |
| | | "", |
| | | // Parent 1 - uses default values for |
| | | // optional-multi-valued-dn-property. |
| | | "dn: cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-parent-dummy", "cn: test parent 1", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", "", |
| | | // Child base entries. |
| | | "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-branch", "cn: test children", "", }; |
| | | |
| | | // JNDI LDAP context. |
| | | private JNDIDirContextAdaptor adaptor = null; |
| | | |
| | | /** |
| | | * Sets up tests |
| | | * |
| | | * @throws Exception |
| | | * If the server could not be initialized. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | // This test suite depends on having the schema available, so |
| | | // we'll start the server. |
| | | TestCaseUtils.startServer(); |
| | | TestCfg.setUp(); |
| | | |
| | | // Add test managed objects. |
| | | TestCaseUtils.addEntries(TEST_LDIF); |
| | | } |
| | | |
| | | /** |
| | | * Tears down test environment. |
| | | * |
| | | * @throws Exception |
| | | * If the test entries could not be removed. |
| | | */ |
| | | @AfterClass |
| | | public void tearDown() throws Exception { |
| | | TestCfg.cleanup(); |
| | | |
| | | // Remove test entries. |
| | | deleteSubtree("cn=test parents,cn=config"); |
| | | } |
| | | |
| | | /** |
| | | * Tests that retrieval can succeed. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testGetManagedObjectSuccess() throws Exception { |
| | | MockConstraint constraint = new MockConstraint(true, false); |
| | | |
| | | try { |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestCfg.addConstraint(constraint); |
| | | |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 1"); |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | |
| | | try { |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Do nothing. |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that retrieval can fail. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testGetManagedObjectFail() throws Exception { |
| | | MockConstraint constraint = new MockConstraint(false, true); |
| | | |
| | | try { |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestCfg.addConstraint(constraint); |
| | | |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | parent.getTestChild("test child 1"); |
| | | } catch (ConfigException e) { |
| | | Throwable cause = e.getCause(); |
| | | if (cause instanceof ConstraintViolationException) { |
| | | ConstraintViolationException cve = (ConstraintViolationException) cause; |
| | | Assert.assertEquals(cve.getMessages().size(), 1); |
| | | Assert.assertSame(cve.getManagedObject().getManagedObjectDefinition(), TestChildCfgDefn.getInstance()); |
| | | } else { |
| | | // Wrong cause. |
| | | throw e; |
| | | } |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | |
| | | try { |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Do nothing. |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that an add constraint can succeed. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAddConstraintSuccess() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | AddListener listener = new AddListener(); |
| | | parent.addTestChildAddListener(listener); |
| | | |
| | | MockConstraint constraint = new MockConstraint(true, false); |
| | | TestCfg.addConstraint(constraint); |
| | | |
| | | try { |
| | | try { |
| | | // Add the entry. |
| | | addEntry(ResultCode.SUCCESS, TEST_CHILD_1); |
| | | } finally { |
| | | try { |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Do nothing. |
| | | } |
| | | } |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | parent.removeTestChildAddListener(listener); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that an add constraint can fail. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAddConstraintFail() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | AddListener listener = new AddListener(); |
| | | parent.addTestChildAddListener(listener); |
| | | |
| | | MockConstraint constraint = new MockConstraint(false, true); |
| | | TestCfg.addConstraint(constraint); |
| | | |
| | | try { |
| | | try { |
| | | // Add the entry. |
| | | addEntry(ResultCode.UNWILLING_TO_PERFORM, TEST_CHILD_1); |
| | | } finally { |
| | | try { |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Do nothing. |
| | | } |
| | | } |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | parent.removeTestChildAddListener(listener); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that a delete constraint can succeed. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testDeleteConstraintSuccess() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | DeleteListener listener = new DeleteListener(); |
| | | parent.addTestChildDeleteListener(listener); |
| | | |
| | | MockConstraint constraint = new MockConstraint(false, true); |
| | | TestCfg.addConstraint(constraint); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | |
| | | // Now delete it - this should trigger the constraint. |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | parent.removeTestChildDeleteListener(listener); |
| | | |
| | | try { |
| | | // Clean up. |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Ignore. |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that a delete constraint can fail. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testDeleteConstraintFail() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | DeleteListener listener = new DeleteListener(); |
| | | parent.addTestChildDeleteListener(listener); |
| | | |
| | | MockConstraint constraint = new MockConstraint(true, false); |
| | | TestCfg.addConstraint(constraint); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | try { |
| | | // Now delete it - this should trigger the constraint. |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | |
| | | // Should not have succeeded. |
| | | Assert.fail("Delete constraint failed to prevent deletion"); |
| | | } catch (OperationNotSupportedException e) { |
| | | // Ignore - this is the expected exception. |
| | | } |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | parent.removeTestChildDeleteListener(listener); |
| | | |
| | | try { |
| | | // Clean up. |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Ignore. |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that a modify constraint can succeed. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChangeConstraintSuccess() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | |
| | | MockConstraint constraint = new MockConstraint(true, false); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestChildCfg child = parent.getTestChild("test child 1"); |
| | | |
| | | TestCfg.addConstraint(constraint); |
| | | ChangeListener listener = new ChangeListener(); |
| | | child.addChangeListener(listener); |
| | | |
| | | // Now modify it. |
| | | String[] changes = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", |
| | | "changetype: modify", "replace: ds-cfg-base-dn", "ds-cfg-base-dn: dc=new value 1,dc=com", |
| | | "ds-cfg-base-dn: dc=new value 2,dc=com", "-", "replace: ds-cfg-group-dn", |
| | | "ds-cfg-group-dn: dc=new value 3,dc=com", "ds-cfg-group-dn: dc=new value 4,dc=com" }; |
| | | |
| | | int result = TestCaseUtils.applyModifications(true, changes); |
| | | Assert.assertEquals(result, ResultCode.SUCCESS.getIntValue()); |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | try { |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Ignore. |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that a modify constraint can fail. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChangeConstraintFail() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | MockConstraint constraint = new MockConstraint(false, true); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestChildCfg child = parent.getTestChild("test child 1"); |
| | | |
| | | TestCfg.addConstraint(constraint); |
| | | ChangeListener listener = new ChangeListener(); |
| | | child.addChangeListener(listener); |
| | | |
| | | // Now modify it. |
| | | String[] changes = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", |
| | | "changetype: modify", "replace: ds-cfg-base-dn", "ds-cfg-base-dn: dc=new value 1,dc=com", |
| | | "ds-cfg-base-dn: dc=new value 2,dc=com", "-", "replace: ds-cfg-group-dn", |
| | | "ds-cfg-group-dn: dc=new value 3,dc=com", "ds-cfg-group-dn: dc=new value 4,dc=com" }; |
| | | |
| | | int result = TestCaseUtils.applyModifications(true, changes); |
| | | Assert.assertEquals(result, ResultCode.UNWILLING_TO_PERFORM.getIntValue()); |
| | | } finally { |
| | | TestCfg.removeConstraint(constraint); |
| | | try { |
| | | deleteSubtree(TEST_CHILD_1_DN); |
| | | } catch (Exception e) { |
| | | // Ignore. |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Add an entry and check its result. |
| | | private void addEntry(ResultCode expected, String... lines) throws Exception { |
| | | Entry entry = TestCaseUtils.makeEntry(lines); |
| | | |
| | | InternalClientConnection conn = InternalClientConnection.getRootConnection(); |
| | | |
| | | AddOperation add = conn.processAdd(entry.getDN(), entry.getObjectClasses(), entry.getUserAttributes(), |
| | | entry.getOperationalAttributes()); |
| | | |
| | | Assert.assertEquals(add.getResultCode(), expected, add.getErrorMessage().toString()); |
| | | } |
| | | |
| | | // Deletes the named sub-tree. |
| | | private void deleteSubtree(String dn) throws Exception { |
| | | getAdaptor().deleteSubtree(new LdapName(dn)); |
| | | } |
| | | |
| | | // Gets the JNDI connection for the test server instance. |
| | | private synchronized JNDIDirContextAdaptor getAdaptor() throws Exception { |
| | | if (adaptor == null) { |
| | | adaptor = JNDIDirContextAdaptor.simpleSSLBind("127.0.0.1", TestCaseUtils.getServerAdminPort(), |
| | | "cn=directory manager", "password"); |
| | | } |
| | | return adaptor; |
| | | } |
| | | |
| | | // Gets the named parent configuration. |
| | | private TestParentCfg getParent(String name) throws IllegalArgumentException, ConfigException { |
| | | ServerManagedObject<RootCfg> root = serverContext.getRootConfigurationManagedObject(); |
| | | TestParentCfg parent = root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name) |
| | | .getConfiguration(); |
| | | return parent; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.opends.server.admin.AdminTestCase; |
| | | import org.opends.server.admin.Configuration; |
| | | import org.opends.server.admin.ConfigurationClient; |
| | | import org.opends.server.admin.LDAPProfile; |
| | | import org.opends.server.admin.ManagedObjectPath; |
| | | import org.opends.server.admin.RelationDefinition; |
| | | import org.opends.server.admin.SingletonRelationDefinition; |
| | | import org.opends.server.admin.TestCfg; |
| | | import org.opends.server.admin.TestChildCfg; |
| | | import org.opends.server.admin.TestChildCfgClient; |
| | | import org.opends.server.admin.TestChildCfgDefn; |
| | | import org.opends.server.admin.TestParentCfgDefn; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * Test cases for the server DNBuilder class. |
| | | */ |
| | | public final class DNBuilderTest extends AdminTestCase { |
| | | |
| | | /** |
| | | * Sets up tests |
| | | * |
| | | * @throws Exception |
| | | * If the server could not be initialized. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | disableClassValidationForProperties(); |
| | | TestCfg.setUp(); |
| | | } |
| | | |
| | | /** |
| | | * Tears down test environment. |
| | | */ |
| | | @AfterClass |
| | | public void tearDown() { |
| | | TestCfg.cleanup(); |
| | | } |
| | | |
| | | /** |
| | | * Tests construction of a DN from a managed object path containing a |
| | | * subordinate one-to-many relationship. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testCreateOneToMany() throws Exception { |
| | | // First create the path. |
| | | ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath |
| | | .emptyPath(); |
| | | |
| | | path = path.child(TestCfg.getTestOneToManyParentRelationDefinition(), "test-parent-1"); |
| | | path = path.child(TestParentCfgDefn.getInstance().getTestChildrenRelationDefinition(), "test-child-1"); |
| | | |
| | | // Now serialize it. |
| | | DN actual = DNBuilder.create(path); |
| | | DN expected = DN.valueOf("cn=test-child-1,cn=test children,cn=test-parent-1,cn=test parents,cn=config"); |
| | | |
| | | assertEquals(actual, expected); |
| | | } |
| | | |
| | | /** |
| | | * Tests construction of a DN from a managed object path containing a |
| | | * subordinate one-to-one relationship. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testCreateOneToOne() throws Exception { |
| | | // First create the path. |
| | | ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath |
| | | .emptyPath(); |
| | | |
| | | SingletonRelationDefinition.Builder<TestChildCfgClient, TestChildCfg> b = new SingletonRelationDefinition.Builder<TestChildCfgClient, TestChildCfg>( |
| | | TestParentCfgDefn.getInstance(), "singleton-test-child", TestChildCfgDefn.getInstance()); |
| | | final SingletonRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = b.getInstance(); |
| | | LDAPProfile.Wrapper wrapper = new LDAPProfile.Wrapper() { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String getRelationRDNSequence(RelationDefinition<?, ?> r) { |
| | | if (r == r2) { |
| | | return "cn=singleton-test-child"; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | }; |
| | | |
| | | path = path.child(TestCfg.getTestOneToManyParentRelationDefinition(), "test-parent-1"); |
| | | path = path.child(r2); |
| | | |
| | | // Now serialize it. |
| | | LDAPProfile.getInstance().pushWrapper(wrapper); |
| | | try { |
| | | DN actual = DNBuilder.create(path); |
| | | DN expected = DN.valueOf("cn=singleton-test-child,cn=test-parent-1,cn=test parents,cn=config"); |
| | | |
| | | assertEquals(actual, expected); |
| | | } finally { |
| | | LDAPProfile.getInstance().popWrapper(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests construction of a DN from a managed object path containing a |
| | | * subordinate one-to-zero-or-one relationship. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected exception occurred. |
| | | */ |
| | | @Test |
| | | public void testCreateOneToZeroOrOne() throws Exception { |
| | | // First create the path. |
| | | ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath |
| | | .emptyPath(); |
| | | |
| | | path = path.child(TestCfg.getTestOneToManyParentRelationDefinition(), "test-parent-1"); |
| | | path = path.child(TestParentCfgDefn.getInstance().getOptionalTestChildRelationDefinition()); |
| | | |
| | | // Now serialize it. |
| | | DN actual = DNBuilder.create(path); |
| | | DN expected = DN.valueOf("cn=optional test child,cn=test-parent-1,cn=test parents,cn=config"); |
| | | |
| | | assertEquals(actual, expected); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import java.util.List; |
| | | import java.util.SortedSet; |
| | | |
| | | import javax.naming.ldap.LdapName; |
| | | |
| | | import org.opends.server.admin.AdminTestCase; |
| | | import org.opends.server.admin.TestCfg; |
| | | import org.opends.server.admin.TestChildCfg; |
| | | import org.opends.server.admin.TestParentCfg; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.testng.Assert; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * Test cases for default behavior on the server-side. |
| | | */ |
| | | public final class DefaultBehaviorTest extends AdminTestCase { |
| | | |
| | | /** |
| | | * A test child add listener. |
| | | */ |
| | | private static class AddListener implements ConfigurationAddListener<TestChildCfg> { |
| | | |
| | | // The child configuration that was added. |
| | | private TestChildCfg child; |
| | | |
| | | /** |
| | | * Creates a new add listener. |
| | | */ |
| | | public AddListener() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * Gets the child configuration checking that it has the expected name. |
| | | * |
| | | * @param expectedName |
| | | * The child's expected name. |
| | | * @return Returns the child configuration. |
| | | */ |
| | | public TestChildCfg getChild(String expectedName) { |
| | | Assert.assertNotNull(child); |
| | | Assert.assertEquals(child.dn().getRDN().getAttributeValue(0).getValue().toString(), expectedName); |
| | | return child; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationAddAcceptable(TestChildCfg configuration, List<Message> unacceptableReasons) { |
| | | child = configuration; |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * A test child change listener. |
| | | */ |
| | | private static class ChangeListener implements ConfigurationChangeListener<TestChildCfg> { |
| | | |
| | | // The child configuration that was changed. |
| | | private TestChildCfg child; |
| | | |
| | | /** |
| | | * Creates a new change listener. |
| | | */ |
| | | public ChangeListener() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange(TestChildCfg configuration) { |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, false); |
| | | } |
| | | |
| | | /** |
| | | * Gets the child configuration checking that it has the expected name. |
| | | * |
| | | * @param expectedName |
| | | * The child's expected name. |
| | | * @return Returns the child configuration. |
| | | */ |
| | | public TestChildCfg getChild(String expectedName) { |
| | | Assert.assertNotNull(child); |
| | | Assert.assertEquals(child.dn().getRDN().getAttributeValue(0).getValue().toString(), expectedName); |
| | | return child; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable(TestChildCfg configuration, List<Message> unacceptableReasons) { |
| | | child = configuration; |
| | | return true; |
| | | } |
| | | |
| | | } |
| | | |
| | | // Test child 1 LDIF. |
| | | private static final String[] TEST_CHILD_1 = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 1", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real" }; |
| | | |
| | | // Test child 2 LDIF. |
| | | private static final String[] TEST_CHILD_2 = new String[] { |
| | | "dn: cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 2", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-base-dn: dc=default value c2v1,dc=com", "ds-cfg-base-dn: dc=default value c2v2,dc=com" }; |
| | | |
| | | // Test child 3 LDIF. |
| | | private static final String[] TEST_CHILD_3 = new String[] { |
| | | "dn: cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 3", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-base-dn: dc=default value c3v1,dc=com", "ds-cfg-base-dn: dc=default value c3v2,dc=com", |
| | | "ds-cfg-group-dn: dc=default value c3v3,dc=com", "ds-cfg-group-dn: dc=default value c3v4,dc=com" }; |
| | | |
| | | // Test child 4 LDIF. |
| | | private static final String[] TEST_CHILD_4 = new String[] { |
| | | "dn: cn=test child 4,cn=test children,cn=test parent 2,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-child-dummy", "cn: test child 4", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real" }; |
| | | |
| | | // Test LDIF. |
| | | private static final String[] TEST_LDIF = new String[] { |
| | | // Base entries. |
| | | "dn: cn=test parents,cn=config", |
| | | "objectclass: top", |
| | | "objectclass: ds-cfg-branch", |
| | | "cn: test parents", |
| | | "", |
| | | // Parent 1 - uses default values for |
| | | // optional-multi-valued-dn-property. |
| | | "dn: cn=test parent 1,cn=test parents,cn=config", |
| | | "objectclass: top", |
| | | "objectclass: ds-cfg-test-parent-dummy", |
| | | "cn: test parent 1", |
| | | "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", |
| | | "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "", |
| | | // Parent 2 - overrides default values for |
| | | // optional-multi-valued-dn-property. |
| | | "dn: cn=test parent 2,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-test-parent-dummy", "cn: test parent 2", "ds-cfg-enabled: true", |
| | | "ds-cfg-java-class: org.opends.server.extensions.UserDefinedVirtualAttributeProvider", |
| | | "ds-cfg-attribute-type: description", "ds-cfg-conflict-behavior: virtual-overrides-real", |
| | | "ds-cfg-base-dn: dc=default value p2v1,dc=com", |
| | | "ds-cfg-base-dn: dc=default value p2v2,dc=com", |
| | | "", |
| | | // Child base entries. |
| | | "dn:cn=test children,cn=test parent 1,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-branch", "cn: test children", "", |
| | | "dn:cn=test children,cn=test parent 2,cn=test parents,cn=config", "objectclass: top", |
| | | "objectclass: ds-cfg-branch", "cn: test children", "" }; |
| | | |
| | | // JNDI LDAP context. |
| | | private JNDIDirContextAdaptor adaptor = null; |
| | | |
| | | /** |
| | | * Sets up tests |
| | | * |
| | | * @throws Exception |
| | | * If the server could not be initialized. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | // This test suite depends on having the schema available, so |
| | | // we'll start the server. |
| | | TestCaseUtils.startServer(); |
| | | TestCfg.setUp(); |
| | | |
| | | // Add test managed objects. |
| | | TestCaseUtils.addEntries(TEST_LDIF); |
| | | } |
| | | |
| | | /** |
| | | * Tears down test environment. |
| | | * |
| | | * @throws Exception |
| | | * If the test entries could not be removed. |
| | | */ |
| | | @AfterClass |
| | | public void tearDown() throws Exception { |
| | | TestCfg.cleanup(); |
| | | |
| | | // Remove test entries. |
| | | deleteSubtree("cn=test parents,cn=config"); |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through an add |
| | | * listener. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAddListenerChildValues1() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | AddListener listener = new AddListener(); |
| | | parent.addTestChildAddListener(listener); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | try { |
| | | assertChild1(listener.getChild("test child 1")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } finally { |
| | | parent.removeTestChildAddListener(listener); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through an add |
| | | * listener. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAddListenerChildValues2() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | AddListener listener = new AddListener(); |
| | | parent.addTestChildAddListener(listener); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_2); |
| | | try { |
| | | assertChild2(listener.getChild("test child 2")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } finally { |
| | | parent.removeTestChildAddListener(listener); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through an add |
| | | * listener. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAddListenerChildValues3() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | AddListener listener = new AddListener(); |
| | | parent.addTestChildAddListener(listener); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_3); |
| | | try { |
| | | assertChild3(listener.getChild("test child 3")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } finally { |
| | | parent.removeTestChildAddListener(listener); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through an add |
| | | * listener. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testAddListenerChildValues4() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 2"); |
| | | AddListener listener = new AddListener(); |
| | | parent.addTestChildAddListener(listener); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_4); |
| | | try { |
| | | assertChild4(listener.getChild("test child 4")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 4,cn=test children,cn=test parent 2,cn=test parents,cn=config"); |
| | | } |
| | | } finally { |
| | | parent.removeTestChildAddListener(listener); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through a change |
| | | * listener. This test replaces the defaulted properties with real values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChangeListenerChildValues1() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestChildCfg child = parent.getTestChild("test child 1"); |
| | | ChangeListener listener = new ChangeListener(); |
| | | child.addChangeListener(listener); |
| | | |
| | | // Now modify it. |
| | | String[] changes = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", |
| | | "changetype: modify", "replace: ds-cfg-base-dn", "ds-cfg-base-dn: dc=new value 1,dc=com", |
| | | "ds-cfg-base-dn: dc=new value 2,dc=com", "-", "replace: ds-cfg-group-dn", |
| | | "ds-cfg-group-dn: dc=new value 3,dc=com", "ds-cfg-group-dn: dc=new value 4,dc=com" }; |
| | | TestCaseUtils.applyModifications(true, changes); |
| | | |
| | | // Make sure that the change listener was notified and the |
| | | // modified child contains the correct values. |
| | | child = listener.getChild("test child 1"); |
| | | |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=new value 1,dc=com", |
| | | "dc=new value 2,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=new value 3,dc=com", |
| | | "dc=new value 4,dc=com"); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through a change |
| | | * listener. This test makes sure that default values inherited from within |
| | | * the modified component itself behave as expected. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChangeListenerChildValues2() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestChildCfg child = parent.getTestChild("test child 1"); |
| | | ChangeListener listener = new ChangeListener(); |
| | | child.addChangeListener(listener); |
| | | |
| | | // Now modify it. |
| | | String[] changes = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", |
| | | "changetype: modify", "replace: ds-cfg-base-dn", "ds-cfg-base-dn: dc=new value 1,dc=com", |
| | | "ds-cfg-base-dn: dc=new value 2,dc=com" }; |
| | | TestCaseUtils.applyModifications(true, changes); |
| | | |
| | | // Make sure that the change listener was notified and the |
| | | // modified child contains the correct values. |
| | | child = listener.getChild("test child 1"); |
| | | |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=new value 1,dc=com", |
| | | "dc=new value 2,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=new value 1,dc=com", |
| | | "dc=new value 2,dc=com"); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through a change |
| | | * listener. This test makes sure that default values inherited from outside |
| | | * the modified component behave as expected. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChangeListenerChildValues3() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestChildCfg child = parent.getTestChild("test child 1"); |
| | | ChangeListener listener = new ChangeListener(); |
| | | child.addChangeListener(listener); |
| | | |
| | | // Now modify it. |
| | | String[] changes = new String[] { |
| | | "dn: cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config", |
| | | "changetype: modify", "replace: ds-cfg-group-dn", "ds-cfg-group-dn: dc=new value 1,dc=com", |
| | | "ds-cfg-group-dn: dc=new value 2,dc=com" }; |
| | | TestCaseUtils.applyModifications(true, changes); |
| | | |
| | | // Make sure that the change listener was notified and the |
| | | // modified child contains the correct values. |
| | | child = listener.getChild("test child 1"); |
| | | |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=domain1,dc=com", "dc=domain2,dc=com", |
| | | "dc=domain3,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=new value 1,dc=com", |
| | | "dc=new value 2,dc=com"); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values when accessed through a change |
| | | * listener. This test makes sure that a component is notified when the |
| | | * default values it inherits from another component are modified. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChangeListenerChildValues4() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | |
| | | try { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | TestChildCfg child = parent.getTestChild("test child 1"); |
| | | ChangeListener listener = new ChangeListener(); |
| | | child.addChangeListener(listener); |
| | | |
| | | // Now modify the parent. |
| | | String[] changes = new String[] { "dn: cn=test parent 1,cn=test parents,cn=config", "changetype: modify", |
| | | "replace: ds-cfg-base-dn", "ds-cfg-base-dn: dc=new value 1,dc=com", |
| | | "ds-cfg-base-dn: dc=new value 2,dc=com" }; |
| | | TestCaseUtils.applyModifications(true, changes); |
| | | |
| | | // Make sure that the change listener was notified and the |
| | | // modified child contains the correct values. |
| | | child = listener.getChild("test child 1"); |
| | | |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=new value 1,dc=com", |
| | | "dc=new value 2,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=new value 1,dc=com", |
| | | "dc=new value 2,dc=com"); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | |
| | | // Undo the modifications. |
| | | String[] changes = new String[] { "dn: cn=test parent 1,cn=test parents,cn=config", "changetype: modify", |
| | | "delete: ds-cfg-base-dn" }; |
| | | TestCaseUtils.applyModifications(true, changes); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChildValues1() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_1); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | assertChild1(parent.getTestChild("test child 1")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 1,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChildValues2() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_2); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | assertChild2(parent.getTestChild("test child 2")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 2,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChildValues3() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_3); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | assertChild3(parent.getTestChild("test child 3")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 3,cn=test children,cn=test parent 1,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that children have correct values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testChildValues4() throws Exception { |
| | | // Add the entry. |
| | | TestCaseUtils.addEntry(TEST_CHILD_4); |
| | | |
| | | try { |
| | | TestParentCfg parent = getParent("test parent 2"); |
| | | assertChild4(parent.getTestChild("test child 4")); |
| | | } finally { |
| | | deleteSubtree("cn=test child 4,cn=test children,cn=test parent 2,cn=test parents,cn=config"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Tests that parent 1 has correct values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testParentValues1() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 1"); |
| | | |
| | | Assert.assertEquals(parent.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(), "dc=domain1,dc=com", "dc=domain2,dc=com", |
| | | "dc=domain3,dc=com"); |
| | | } |
| | | |
| | | /** |
| | | * Tests that parent 2 has correct values. |
| | | * |
| | | * @throws Exception |
| | | * If the test unexpectedly fails. |
| | | */ |
| | | @Test |
| | | public void testParentValues2() throws Exception { |
| | | TestParentCfg parent = getParent("test parent 2"); |
| | | |
| | | Assert.assertEquals(parent.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(parent.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(parent.getOptionalMultiValuedDNProperty(), "dc=default value p2v1,dc=com", |
| | | "dc=default value p2v2,dc=com"); |
| | | } |
| | | |
| | | // Assert that the values of child 1 are correct. |
| | | private void assertChild1(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=domain1,dc=com", "dc=domain2,dc=com", |
| | | "dc=domain3,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=domain1,dc=com", "dc=domain2,dc=com", |
| | | "dc=domain3,dc=com"); |
| | | } |
| | | |
| | | // Assert that the values of child 2 are correct. |
| | | private void assertChild2(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value c2v1,dc=com", |
| | | "dc=default value c2v2,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value c2v1,dc=com", |
| | | "dc=default value c2v2,dc=com"); |
| | | } |
| | | |
| | | // Assert that the values of child 3 are correct. |
| | | private void assertChild3(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value c3v1,dc=com", |
| | | "dc=default value c3v2,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value c3v3,dc=com", |
| | | "dc=default value c3v4,dc=com"); |
| | | } |
| | | |
| | | // Assert that the values of child 4 are correct. |
| | | private void assertChild4(TestChildCfg child) { |
| | | Assert.assertEquals(child.getMandatoryClassProperty(), |
| | | "org.opends.server.extensions.UserDefinedVirtualAttributeProvider"); |
| | | Assert.assertEquals(child.getMandatoryReadOnlyAttributeTypeProperty(), |
| | | DirectoryServer.getAttributeType("description")); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty1(), "dc=default value p2v1,dc=com", |
| | | "dc=default value p2v2,dc=com"); |
| | | assertDNSetEquals(child.getOptionalMultiValuedDNProperty2(), "dc=default value p2v1,dc=com", |
| | | "dc=default value p2v2,dc=com"); |
| | | } |
| | | |
| | | // Asserts that the actual set of DNs contains the expected values. |
| | | private void assertDNSetEquals(SortedSet<DN> actual, String... expected) { |
| | | String[] actualStrings = new String[actual.size()]; |
| | | int i = 0; |
| | | for (DN dn : actual) { |
| | | actualStrings[i] = dn.toString(); |
| | | i++; |
| | | } |
| | | Assert.assertEqualsNoOrder(actualStrings, expected); |
| | | } |
| | | |
| | | // Deletes the named sub-tree. |
| | | private void deleteSubtree(String dn) throws Exception { |
| | | getAdaptor().deleteSubtree(new LdapName(dn)); |
| | | } |
| | | |
| | | // Gets the JNDI connection for the test server instance. |
| | | private synchronized JNDIDirContextAdaptor getAdaptor() throws Exception { |
| | | if (adaptor == null) { |
| | | adaptor = JNDIDirContextAdaptor.simpleSSLBind("127.0.0.1", TestCaseUtils.getServerAdminPort(), |
| | | "cn=directory manager", "password"); |
| | | } |
| | | return adaptor; |
| | | } |
| | | |
| | | // Gets the named parent configuration. |
| | | private TestParentCfg getParent(String name) throws IllegalArgumentException, ConfigException { |
| | | ServerManagedObject<RootCfg> root = serverContext.getRootConfigurationManagedObject(); |
| | | TestParentCfg parent = root.getChild(TestCfg.getTestOneToManyParentRelationDefinition(), name) |
| | | .getConfiguration(); |
| | | return parent; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2007-2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import static org.fest.assertions.Assertions.*; |
| | | import static org.mockito.Mockito.*; |
| | | |
| | | import java.util.Arrays; |
| | | import org.forgerock.opendj.admin.server.RootCfg; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.Entry; |
| | | import org.forgerock.opendj.ldap.TestCaseUtils; |
| | | import org.mockito.ArgumentCaptor; |
| | | import org.opends.server.admin.AdminTestCase; |
| | | import org.opends.server.admin.TestCfg; |
| | | import org.opends.server.admin.TestParentCfg; |
| | | import org.opends.server.api.ConfigAddListener; |
| | | import org.opends.server.api.ConfigChangeListener; |
| | | import org.opends.server.api.ConfigDeleteListener; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.ConfigurationRepository; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.Test; |
| | | |
| | | |
| | | @SuppressWarnings({"javadoc", "rawtypes", "unchecked"}) |
| | | public class ListenerTest extends AdminTestCase { |
| | | |
| | | private static final DN ROOT_CONFIG_DN = DN.valueOf("cn=config"); |
| | | private static final DN TEST_PARENTS_DN = DN.valueOf("cn=test parents,cn=config"); |
| | | |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | disableClassValidationForProperties(); |
| | | TestCfg.setUp(); |
| | | } |
| | | |
| | | @AfterClass |
| | | public void tearDown() throws Exception { |
| | | TestCfg.cleanup(); |
| | | } |
| | | |
| | | private Entry getTestParentEntry() throws Exception { |
| | | return TestCaseUtils.makeEntry( |
| | | "dn: cn=test parents,cn=config", |
| | | "objectclass: top", |
| | | "objectclass: ds-cfg-branch", |
| | | "cn: test parents"); |
| | | } |
| | | |
| | | /** |
| | | * Create a mock of ConfigurationRepository with provided DNs registered. |
| | | */ |
| | | private ConfigurationRepository createConfigRepositoryWithDNs(DN...dns) throws ConfigException { |
| | | ConfigurationRepository configRepository = mock(ConfigurationRepository.class); |
| | | for (DN dn : dns) { |
| | | when(configRepository.hasEntry(dn)).thenReturn(true); |
| | | } |
| | | return configRepository; |
| | | } |
| | | |
| | | /** Register a listener for test parent entry and return the actual registered listener */ |
| | | private ConfigAddListener registerAddListenerForTestParent(ConfigurationRepository configRepository, |
| | | ServerManagedObject<RootCfg> root, ConfigurationAddListener<TestParentCfg> parentListener) |
| | | throws Exception { |
| | | root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | ArgumentCaptor<ConfigAddListener> registered = ArgumentCaptor.forClass(ConfigAddListener.class); |
| | | verify(configRepository).registerAddListener(eq(TEST_PARENTS_DN), registered.capture()); |
| | | return registered.getValue(); |
| | | } |
| | | |
| | | /** Register a listener for test parent entry in delayed scenario and return the actual registered listener */ |
| | | private DelayedConfigAddListener registerAddListenerForTestParentDelayed(ConfigurationRepository configRepository, |
| | | ServerManagedObject<RootCfg> root, ConfigurationAddListener<TestParentCfg> parentListener) |
| | | throws Exception { |
| | | root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | ArgumentCaptor<DelayedConfigAddListener> registered = ArgumentCaptor.forClass(DelayedConfigAddListener.class); |
| | | verify(configRepository).registerAddListener(eq(ROOT_CONFIG_DN), registered.capture()); |
| | | return registered.getValue(); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterAddListenerWithInstantiableRelationImmediate() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN, TEST_PARENTS_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), |
| | | mock(ConfigurationAddListener.class)); |
| | | |
| | | verify(configRepository).registerAddListener(eq(TEST_PARENTS_DN), |
| | | isA(ConfigAddListener.class)); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterAddListenerWithInstantiableRelationDelayed() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | ConfigurationAddListener<TestParentCfg> parentListener = mock(ConfigurationAddListener.class); |
| | | root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | ArgumentCaptor<DelayedConfigAddListener> registered = ArgumentCaptor.forClass(DelayedConfigAddListener.class); |
| | | verify(configRepository).registerAddListener(eq(ROOT_CONFIG_DN), registered.capture()); |
| | | // check that actual listener is the one provided to the root |
| | | ConfigurationAddListener<?> actualListener = |
| | | ((ServerManagedObjectAddListenerAdaptor<?>) |
| | | ((ConfigAddListenerAdaptor<?>) registered.getValue().getDelayedAddListener()). |
| | | getServerManagedObjectAddListener()).getConfigurationAddListener(); |
| | | assertThat(actualListener).isEqualTo(parentListener); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterAddListenerWithInstantiableRelationDelayedThenActualized() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | // register a listener to root |
| | | ConfigurationAddListener<TestParentCfg> parentListener = mock(ConfigurationAddListener.class); |
| | | root.registerAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | // get the delayed listener registered to configuration repository |
| | | ArgumentCaptor<DelayedConfigAddListener> registered = ArgumentCaptor.forClass(DelayedConfigAddListener.class); |
| | | verify(configRepository).registerAddListener(eq(ROOT_CONFIG_DN), registered.capture()); |
| | | |
| | | // now simulate the add of target entry |
| | | String parentDN = "cn=test parents,cn=config"; |
| | | when(configRepository.hasEntry(DN.valueOf(parentDN))).thenReturn(true); |
| | | registered.getValue().applyConfigurationAdd(getTestParentEntry()); |
| | | |
| | | // check that listener is added for target entry and deleted for its parent entry |
| | | ConfigAddListenerAdaptor listener = |
| | | (ConfigAddListenerAdaptor<?>) registered.getValue().getDelayedAddListener(); |
| | | verify(configRepository).registerAddListener(DN.valueOf(parentDN), listener); |
| | | verify(configRepository).deregisterAddListener(ROOT_CONFIG_DN, registered.getValue()); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterAddListenerWithOptionalRelation() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | root.registerAddListener(TestCfg.getTestOneToZeroOrOneParentRelationDefinition(), |
| | | mock(ConfigurationAddListener.class)); |
| | | |
| | | verify(configRepository).registerAddListener(eq(ROOT_CONFIG_DN), |
| | | isA(ConfigAddListener.class)); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterDeleteListenerWithInstantiableRelationImmediate() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN, TEST_PARENTS_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | root.registerDeleteListener(TestCfg.getTestOneToManyParentRelationDefinition(), |
| | | mock(ConfigurationDeleteListener.class)); |
| | | |
| | | verify(configRepository).registerDeleteListener(eq(TEST_PARENTS_DN), |
| | | isA(ConfigDeleteListener.class)); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterDeleteListenerWithInstantiableRelationDelayed() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | ConfigurationDeleteListener<TestParentCfg> parentListener = mock(ConfigurationDeleteListener.class); |
| | | root.registerDeleteListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | ArgumentCaptor<DelayedConfigAddListener> argument = ArgumentCaptor.forClass(DelayedConfigAddListener.class); |
| | | verify(configRepository).registerAddListener(eq(ROOT_CONFIG_DN), argument.capture()); |
| | | // check that actual listener is the one provided to the root |
| | | ConfigurationDeleteListener actualListener = |
| | | ((ServerManagedObjectDeleteListenerAdaptor) |
| | | ((ConfigDeleteListenerAdaptor)argument.getValue().getDelayedDeleteListener()). |
| | | getServerManagedObjectDeleteListener()).getConfigurationDeleteListener(); |
| | | assertThat(actualListener).isEqualTo(parentListener); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterDeleteListenerWithOptionalRelation() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | root.registerDeleteListener(TestCfg.getTestOneToZeroOrOneParentRelationDefinition(), |
| | | mock(ConfigurationDeleteListener.class)); |
| | | |
| | | verify(configRepository).registerDeleteListener(eq(ROOT_CONFIG_DN), |
| | | isA(ConfigDeleteListener.class)); |
| | | } |
| | | |
| | | @Test |
| | | public void testRegisterChangeListener() throws Exception { |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | root.setConfigDN(ROOT_CONFIG_DN); |
| | | |
| | | root.registerChangeListener(mock(ConfigurationChangeListener.class)); |
| | | |
| | | verify(configRepository).registerChangeListener(eq(ROOT_CONFIG_DN), |
| | | isA(ConfigChangeListener.class)); |
| | | } |
| | | |
| | | @Test |
| | | public void testDeregisterAddListenerWithInstantiableRelationImmediate() throws Exception { |
| | | // arrange |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN, TEST_PARENTS_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | ConfigurationAddListener<TestParentCfg> parentListener = mock(ConfigurationAddListener.class); |
| | | ConfigAddListener registeredListener = |
| | | registerAddListenerForTestParent(configRepository, root, parentListener); |
| | | when(configRepository.getAddListeners(TEST_PARENTS_DN)).thenReturn(Arrays.asList(registeredListener)); |
| | | |
| | | // act |
| | | root.deregisterAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | // assert |
| | | verify(configRepository).deregisterAddListener(eq(TEST_PARENTS_DN), same(registeredListener)); |
| | | } |
| | | |
| | | @Test |
| | | public void testDeregisterAddListenerWithInstantiableRelationDelayed() throws Exception { |
| | | // arrange |
| | | ConfigurationRepository configRepository = createConfigRepositoryWithDNs(ROOT_CONFIG_DN); |
| | | ServerManagementContext context = new ServerManagementContext(configRepository); |
| | | ServerManagedObject<RootCfg> root = context.getRootConfigurationManagedObject(); |
| | | |
| | | ConfigurationAddListener<TestParentCfg> parentListener = mock(ConfigurationAddListener.class); |
| | | ConfigAddListener registeredListener = |
| | | registerAddListenerForTestParentDelayed(configRepository, root, parentListener); |
| | | when(configRepository.getAddListeners(ROOT_CONFIG_DN)).thenReturn(Arrays.asList(registeredListener)); |
| | | |
| | | // act |
| | | root.deregisterAddListener(TestCfg.getTestOneToManyParentRelationDefinition(), parentListener); |
| | | |
| | | // assert |
| | | verify(configRepository).deregisterAddListener(eq(ROOT_CONFIG_DN), same(registeredListener)); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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 legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * 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 legal-notices/CDDLv1_0.txt. |
| | | * 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 2008 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.admin.server; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.opends.server.admin.Constraint; |
| | | import org.opends.server.admin.client.ClientConstraintHandler; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.config.ConfigurationRepository; |
| | | import org.testng.Assert; |
| | | |
| | | /** |
| | | * A mock constraint which can be configured to refuse various types of |
| | | * operation. |
| | | */ |
| | | public final class MockConstraint extends Constraint { |
| | | |
| | | /** |
| | | * Mock server constraint handler. |
| | | */ |
| | | private class Handler extends ServerConstraintHandler { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isDeleteAllowed(ServerManagedObject<?> managedObject, |
| | | Collection<LocalizableMessage> unacceptableReasons) throws ConfigException { |
| | | if (!isDeleteAllowed) { |
| | | unacceptableReasons.add(LocalizableMessage.raw("Configuration cannot be deleted.")); |
| | | } |
| | | |
| | | return isDeleteAllowed; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isUsable(ServerManagedObject<?> managedObject, |
| | | Collection<LocalizableMessage> unacceptableReasons) throws ConfigException { |
| | | if (!isUsable) { |
| | | unacceptableReasons.add(LocalizableMessage.raw("Configuration is not usable.")); |
| | | } |
| | | |
| | | return isUsable; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void performPostAdd(ServerManagedObject<?> managedObject) throws ConfigException { |
| | | // Make sure that the associated config entry exists. |
| | | DN targetDN = managedObject.getDN(); |
| | | Assert.assertTrue(configRepository.hasEntry(targetDN)); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void performPostDelete(ServerManagedObject<?> managedObject) throws ConfigException { |
| | | // Make sure that the associated config entry does not exist. |
| | | DN targetDN = managedObject.getDN(); |
| | | Assert.assertTrue(configRepository.hasEntry(targetDN)); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void performPostModify(ServerManagedObject<?> managedObject) throws ConfigException { |
| | | // Make sure that the associated config entry exists. |
| | | DN targetDN = managedObject.getDN(); |
| | | Assert.assertTrue(configRepository.hasEntry(targetDN)); |
| | | } |
| | | |
| | | } |
| | | |
| | | // Determines if delete operations are allowed. |
| | | private final boolean isDeleteAllowed; |
| | | |
| | | // Determines if configurations can be decoded. |
| | | private final boolean isUsable; |
| | | |
| | | private final ConfigurationRepository configRepository; |
| | | |
| | | /** |
| | | * Creates a new mock constraint. |
| | | * |
| | | * @param isUsable |
| | | * Determines if configurations can be decoded. |
| | | * @param isDeleteAllowed |
| | | * Determines if delete operations are allowed. |
| | | * @param configRepository |
| | | * Configuration entries. |
| | | */ |
| | | public MockConstraint(boolean isUsable, boolean isDeleteAllowed, ConfigurationRepository configRepository) { |
| | | this.isUsable = isUsable; |
| | | this.isDeleteAllowed = isDeleteAllowed; |
| | | this.configRepository = configRepository; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<ClientConstraintHandler> getClientConstraintHandlers() { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<ServerConstraintHandler> getServerConstraintHandlers() { |
| | | return Collections.<ServerConstraintHandler> singleton(new Handler()); |
| | | } |
| | | |
| | | } |