From 2fef5aa0046548cb88034553f522d907195a19f7 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 02 Dec 2013 10:47:18 +0000
Subject: [PATCH] OpenDJ 3 : config framework
---
opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java | 2014 ++++++++++++++++++++++++++--------------------------------
1 files changed, 915 insertions(+), 1,099 deletions(-)
diff --git a/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java b/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java
index a028505..33d3c7b 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/AggregationPropertyDefinition.java
@@ -26,12 +26,6 @@
*/
package org.opends.server.admin;
-
-
-import static org.opends.messages.AdminMessages.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.util.Validator.*;
-
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
@@ -44,7 +38,6 @@
import java.util.MissingResourceException;
import java.util.SortedSet;
-import org.opends.messages.Message;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.ClientConstraintHandler;
import org.opends.server.admin.client.CommunicationException;
@@ -58,1147 +51,970 @@
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.server.ServerManagedObjectChangeListener;
import org.opends.server.admin.server.ServerManagementContext;
-import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.config.ConfigException;
-import org.opends.server.loggers.ErrorLogger;
-import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.ConfigChangeResult;
+import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.ldap.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.ResultCode;
-import org.opends.server.util.StaticUtils;
-
-
+import org.forgerock.opendj.ldap.ResultCode;
/**
* Aggregation property definition.
* <p>
- * An aggregation property names one or more managed objects which are
- * required by the managed object associated with this property. An
- * aggregation property definition takes care to perform referential
- * integrity checks: referenced managed objects cannot be deleted. Nor
- * can an aggregation reference non-existent managed objects.
- * Referential integrity checks are <b>not</b> performed during value
- * validation. Instead they are performed when changes to the managed
- * object are committed.
+ * An aggregation property names one or more managed objects which are required
+ * by the managed object associated with this property. An aggregation property
+ * definition takes care to perform referential integrity checks: referenced
+ * managed objects cannot be deleted. Nor can an aggregation reference
+ * non-existent managed objects. Referential integrity checks are <b>not</b>
+ * performed during value validation. Instead they are performed when changes to
+ * the managed object are committed.
* <p>
- * An aggregation property definition can optionally identify two
- * properties:
+ * An aggregation property definition can optionally identify two properties:
* <ul>
- * <li>an <code>enabled</code> property in the aggregated managed
- * object - the property must be a {@link BooleanPropertyDefinition}
- * and indicate whether the aggregated managed object is enabled or
- * not. If specified, the administration framework will prevent the
- * aggregated managed object from being disabled while it is
- * referenced
- * <li>an <code>enabled</code> property in this property's managed
- * object - the property must be a {@link BooleanPropertyDefinition}
- * and indicate whether this property's managed object is enabled or
- * not. If specified, and as long as there is an equivalent
- * <code>enabled</code> property defined for the aggregated managed
- * object, the <code>enabled</code> property in the aggregated
- * managed object will only be checked when this property is true.
+ * <li>an <code>enabled</code> property in the aggregated managed object - the
+ * property must be a {@link BooleanPropertyDefinition} and indicate whether the
+ * aggregated managed object is enabled or not. If specified, the administration
+ * framework will prevent the aggregated managed object from being disabled
+ * while it is referenced
+ * <li>an <code>enabled</code> property in this property's managed object - the
+ * property must be a {@link BooleanPropertyDefinition} and indicate whether
+ * this property's managed object is enabled or not. If specified, and as long
+ * as there is an equivalent <code>enabled</code> property defined for the
+ * aggregated managed object, the <code>enabled</code> property in the
+ * aggregated managed object will only be checked when this property is true.
* </ul>
- * In other words, these properties can be used to make sure that
- * referenced managed objects are not disabled while they are
- * referenced.
+ * In other words, these properties can be used to make sure that referenced
+ * managed objects are not disabled while they are referenced.
*
* @param <C>
- * The type of client managed object configuration that this
- * aggregation property definition refers to.
+ * The type of client managed object configuration that this
+ * aggregation property definition refers to.
* @param <S>
- * The type of server managed object configuration that this
- * aggregation property definition refers to.
+ * The type of server managed object configuration that this
+ * aggregation property definition refers to.
*/
-public final class AggregationPropertyDefinition
- <C extends ConfigurationClient, S extends Configuration>
- extends PropertyDefinition<String> {
+public final class AggregationPropertyDefinition<C extends ConfigurationClient, S extends Configuration> extends
+ PropertyDefinition<String> {
- /**
- * An interface for incrementally constructing aggregation property
- * definitions.
- *
- * @param <C>
- * The type of client managed object configuration that
- * this aggregation property definition refers to.
- * @param <S>
- * The type of server managed object configuration that
- * this aggregation property definition refers to.
- */
- public static class Builder
- <C extends ConfigurationClient, S extends Configuration>
- extends AbstractBuilder<String, AggregationPropertyDefinition<C, S>> {
+ /**
+ * An interface for incrementally constructing aggregation property
+ * definitions.
+ *
+ * @param <C>
+ * The type of client managed object configuration that this
+ * aggregation property definition refers to.
+ * @param <S>
+ * The type of server managed object configuration that this
+ * aggregation property definition refers to.
+ */
+ public static class Builder<C extends ConfigurationClient, S extends Configuration> extends
+ AbstractBuilder<String, AggregationPropertyDefinition<C, S>> {
+
+ // The string representation of the managed object path specifying
+ // the parent of the aggregated managed objects.
+ private String parentPathString = null;
+
+ // The name of a relation in the parent managed object which
+ // contains the aggregated managed objects.
+ private String rdName = null;
+
+ // The condition which is used to determine if a referenced
+ // managed object is enabled.
+ private Condition targetIsEnabledCondition = Conditions.TRUE;
+
+ // The condition which is used to determine whether or not
+ // referenced managed objects need to be enabled.
+ private Condition targetNeedsEnablingCondition = Conditions.TRUE;
+
+ // Private constructor
+ private Builder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
+ super(d, propertyName);
+ }
+
+ /**
+ * Sets the name of the managed object which is the parent of the
+ * aggregated managed objects.
+ * <p>
+ * This must be defined before the property definition can be built.
+ *
+ * @param pathString
+ * The string representation of the managed object path
+ * specifying the parent of the aggregated managed objects.
+ */
+ public final void setParentPath(String pathString) {
+ this.parentPathString = pathString;
+ }
+
+ /**
+ * Sets the relation in the parent managed object which contains the
+ * aggregated managed objects.
+ * <p>
+ * This must be defined before the property definition can be built.
+ *
+ * @param rdName
+ * The name of a relation in the parent managed object which
+ * contains the aggregated managed objects.
+ */
+ public final void setRelationDefinition(String rdName) {
+ this.rdName = rdName;
+ }
+
+ /**
+ * Sets the condition which is used to determine if a referenced managed
+ * object is enabled. By default referenced managed objects are assumed
+ * to always be enabled.
+ *
+ * @param condition
+ * The condition which is used to determine if a referenced
+ * managed object is enabled.
+ */
+ public final void setTargetIsEnabledCondition(Condition condition) {
+ this.targetIsEnabledCondition = condition;
+ }
+
+ /**
+ * Sets the condition which is used to determine whether or not
+ * referenced managed objects need to be enabled. By default referenced
+ * managed objects must always be enabled.
+ *
+ * @param condition
+ * The condition which is used to determine whether or not
+ * referenced managed objects need to be enabled.
+ */
+ public final void setTargetNeedsEnablingCondition(Condition condition) {
+ this.targetNeedsEnablingCondition = condition;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected AggregationPropertyDefinition<C, S> buildInstance(AbstractManagedObjectDefinition<?, ?> d,
+ String propertyName, EnumSet<PropertyOption> options, AdministratorAction adminAction,
+ DefaultBehaviorProvider<String> defaultBehavior) {
+ // Make sure that the parent path has been defined.
+ if (parentPathString == null) {
+ throw new IllegalStateException("Parent path undefined");
+ }
+
+ // Make sure that the relation definition has been defined.
+ if (rdName == null) {
+ throw new IllegalStateException("Relation definition undefined");
+ }
+
+ return new AggregationPropertyDefinition<C, S>(d, propertyName, options, adminAction, defaultBehavior,
+ parentPathString, rdName, targetNeedsEnablingCondition, targetIsEnabledCondition);
+ }
+
+ }
+
+ /**
+ * A change listener which prevents the named component from being disabled.
+ */
+ private class ReferentialIntegrityChangeListener implements ServerManagedObjectChangeListener<S> {
+
+ // The error message which should be returned if an attempt is
+ // made to disable the referenced component.
+ private final LocalizableMessage message;
+
+ // The path of the referenced component.
+ private final ManagedObjectPath<C, S> path;
+
+ // Creates a new referential integrity delete listener.
+ private ReferentialIntegrityChangeListener(ManagedObjectPath<C, S> path, LocalizableMessage message) {
+ this.path = path;
+ this.message = message;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationChange(ServerManagedObject<? extends S> mo) {
+ try {
+ if (targetIsEnabledCondition.evaluate(mo)) {
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+ } catch (ConfigException e) {
+ // This should not happen - ignore it and throw an exception
+ // anyway below.
+ }
+
+ // This should not happen - the previous call-back should have
+ // trapped this.
+ throw new IllegalStateException("Attempting to disable a referenced "
+ + relationDefinition.getChildDefinition().getUserFriendlyName());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationChangeAcceptable(ServerManagedObject<? extends S> mo,
+ List<LocalizableMessage> unacceptableReasons) {
+ // Always prevent the referenced component from being
+ // disabled.
+ try {
+ if (!targetIsEnabledCondition.evaluate(mo)) {
+ unacceptableReasons.add(message);
+ return false;
+ } else {
+ return true;
+ }
+ } catch (ConfigException e) {
+ // The condition could not be evaluated.
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ LocalizableMessage message = ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION.get(mo.getManagedObjectDefinition()
+ .getUserFriendlyName(), String.valueOf(mo.getDN()), StaticUtils.getExceptionLocalizableMessage(e));
+ ErrorLogger.logError(message);
+ unacceptableReasons.add(message);
+ return false;
+ }
+ }
+
+ // Gets the path associated with this listener.
+ private ManagedObjectPath<C, S> getManagedObjectPath() {
+ return path;
+ }
+
+ }
+
+ /**
+ * A delete listener which prevents the named component from being deleted.
+ */
+ private class ReferentialIntegrityDeleteListener implements ConfigurationDeleteListener<S> {
+
+ // The DN of the referenced configuration entry.
+ private final DN dn;
+
+ // The error message which should be returned if an attempt is
+ // made to delete the referenced component.
+ private final LocalizableMessage message;
+
+ // Creates a new referential integrity delete listener.
+ private ReferentialIntegrityDeleteListener(DN dn, LocalizableMessage message) {
+ this.dn = dn;
+ this.message = message;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationDelete(S configuration) {
+ // This should not happen - the
+ // isConfigurationDeleteAcceptable() call-back should have
+ // trapped this.
+ if (configuration.dn().equals(dn)) {
+ // This should not happen - the
+ // isConfigurationDeleteAcceptable() call-back should have
+ // trapped this.
+ throw new IllegalStateException("Attempting to delete a referenced "
+ + relationDefinition.getChildDefinition().getUserFriendlyName());
+ } else {
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationDeleteAcceptable(S configuration, List<LocalizableMessage> unacceptableReasons) {
+ if (configuration.dn().equals(dn)) {
+ // Always prevent deletion of the referenced component.
+ unacceptableReasons.add(message);
+ return false;
+ }
+
+ return true;
+ }
+
+ }
+
+ /**
+ * The server-side constraint handler implementation.
+ */
+ private class ServerHandler extends ServerConstraintHandler {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isUsable(ServerManagedObject<?> managedObject, Collection<LocalizableMessage> unacceptableReasons)
+ throws ConfigException {
+ SortedSet<String> names = managedObject.getPropertyValues(AggregationPropertyDefinition.this);
+ ServerManagementContext context = ServerManagementContext.getInstance();
+ LocalizableMessage thisUFN = managedObject.getManagedObjectDefinition().getUserFriendlyName();
+ String thisDN = managedObject.getDN().toString();
+ LocalizableMessage thatUFN = getRelationDefinition().getUserFriendlyName();
+
+ boolean isUsable = true;
+ boolean needsEnabling = targetNeedsEnablingCondition.evaluate(managedObject);
+ for (String name : names) {
+ ManagedObjectPath<C, S> path = getChildPath(name);
+ String thatDN = path.toDN().toString();
+
+ if (!context.managedObjectExists(path)) {
+ LocalizableMessage msg = ERR_SERVER_REFINT_DANGLING_REFERENCE.get(name, getName(), thisUFN, thisDN, thatUFN,
+ thatDN);
+ unacceptableReasons.add(msg);
+ isUsable = false;
+ } else if (needsEnabling) {
+ // Check that the referenced component is enabled if
+ // required.
+ ServerManagedObject<? extends S> ref = context.getManagedObject(path);
+ if (!targetIsEnabledCondition.evaluate(ref)) {
+ LocalizableMessage msg = ERR_SERVER_REFINT_TARGET_DISABLED.get(name, getName(), thisUFN, thisDN, thatUFN,
+ thatDN);
+ unacceptableReasons.add(msg);
+ isUsable = false;
+ }
+ }
+ }
+
+ return isUsable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void performPostAdd(ServerManagedObject<?> managedObject) throws ConfigException {
+ // First make sure existing listeners associated with this
+ // managed object are removed. This is required in order to
+ // prevent multiple change listener registrations from
+ // occurring, for example if this call-back is invoked multiple
+ // times after the same add event.
+ performPostDelete(managedObject);
+
+ // Add change and delete listeners against all referenced
+ // components.
+ LocalizableMessage thisUFN = managedObject.getManagedObjectDefinition().getUserFriendlyName();
+ String thisDN = managedObject.getDN().toString();
+ LocalizableMessage thatUFN = getRelationDefinition().getUserFriendlyName();
+
+ // Referenced managed objects will only need a change listener
+ // if they have can be disabled.
+ boolean needsChangeListeners = targetNeedsEnablingCondition.evaluate(managedObject);
+
+ // Delete listeners need to be registered against the parent
+ // entry of the referenced components.
+ ServerManagementContext context = ServerManagementContext.getInstance();
+ ManagedObjectPath<?, ?> parentPath = getParentPath();
+ ServerManagedObject<?> parent = context.getManagedObject(parentPath);
+
+ // Create entries in the listener tables.
+ List<ReferentialIntegrityDeleteListener> dlist = new LinkedList<ReferentialIntegrityDeleteListener>();
+ deleteListeners.put(managedObject.getDN(), dlist);
+
+ List<ReferentialIntegrityChangeListener> clist = new LinkedList<ReferentialIntegrityChangeListener>();
+ changeListeners.put(managedObject.getDN(), clist);
+
+ for (String name : managedObject.getPropertyValues(AggregationPropertyDefinition.this)) {
+ ManagedObjectPath<C, S> path = getChildPath(name);
+ DN dn = path.toDN();
+ String thatDN = dn.toString();
+
+ // Register the delete listener.
+ LocalizableMessage msg = ERR_SERVER_REFINT_CANNOT_DELETE.get(thatUFN, thatDN, getName(), thisUFN, thisDN);
+ ReferentialIntegrityDeleteListener dl = new ReferentialIntegrityDeleteListener(dn, msg);
+ parent.registerDeleteListener(getRelationDefinition(), dl);
+ dlist.add(dl);
+
+ // Register the change listener if required.
+ if (needsChangeListeners) {
+ ServerManagedObject<? extends S> ref = context.getManagedObject(path);
+ msg = ERR_SERVER_REFINT_CANNOT_DISABLE.get(thatUFN, thatDN, getName(), thisUFN, thisDN);
+ ReferentialIntegrityChangeListener cl = new ReferentialIntegrityChangeListener(path, msg);
+ ref.registerChangeListener(cl);
+ clist.add(cl);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void performPostDelete(ServerManagedObject<?> managedObject) throws ConfigException {
+ // Remove any registered delete and change listeners.
+ ServerManagementContext context = ServerManagementContext.getInstance();
+ DN dn = managedObject.getDN();
+
+ // Delete listeners need to be deregistered against the parent
+ // entry of the referenced components.
+ ManagedObjectPath<?, ?> parentPath = getParentPath();
+ ServerManagedObject<?> parent = context.getManagedObject(parentPath);
+ if (deleteListeners.containsKey(dn)) {
+ for (ReferentialIntegrityDeleteListener dl : deleteListeners.get(dn)) {
+ parent.deregisterDeleteListener(getRelationDefinition(), dl);
+ }
+ deleteListeners.remove(dn);
+ }
+
+ // Change listeners need to be deregistered from their
+ // associated referenced component.
+ if (changeListeners.containsKey(dn)) {
+ for (ReferentialIntegrityChangeListener cl : changeListeners.get(dn)) {
+ ManagedObjectPath<C, S> path = cl.getManagedObjectPath();
+ ServerManagedObject<? extends S> ref = context.getManagedObject(path);
+ ref.deregisterChangeListener(cl);
+ }
+ changeListeners.remove(dn);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void performPostModify(ServerManagedObject<?> managedObject) throws ConfigException {
+ // Remove all the constraints associated with this managed
+ // object and then re-register them.
+ performPostDelete(managedObject);
+ performPostAdd(managedObject);
+ }
+ }
+
+ /**
+ * The client-side constraint handler implementation which enforces
+ * referential integrity when aggregating managed objects are added or
+ * modified.
+ */
+ private class SourceClientHandler extends ClientConstraintHandler {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isAddAcceptable(ManagementContext context, ManagedObject<?> managedObject,
+ Collection<LocalizableMessage> unacceptableReasons) throws AuthorizationException, CommunicationException {
+ // If all of this managed object's "enabled" properties are true
+ // then any referenced managed objects must also be enabled.
+ boolean needsEnabling = targetNeedsEnablingCondition.evaluate(context, managedObject);
+
+ // Check the referenced managed objects exist and, if required,
+ // are enabled.
+ boolean isAcceptable = true;
+ LocalizableMessage ufn = getRelationDefinition().getUserFriendlyName();
+ for (String name : managedObject.getPropertyValues(AggregationPropertyDefinition.this)) {
+ // Retrieve the referenced managed object and make sure it
+ // exists.
+ ManagedObjectPath<?, ?> path = getChildPath(name);
+ ManagedObject<?> ref;
+ try {
+ ref = context.getManagedObject(path);
+ } catch (DefinitionDecodingException e) {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name, getName(), e.getLocalizableMessageObject());
+ unacceptableReasons.add(msg);
+ isAcceptable = false;
+ continue;
+ } catch (ManagedObjectDecodingException e) {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name, getName(), e.getLocalizableMessageObject());
+ unacceptableReasons.add(msg);
+ isAcceptable = false;
+ continue;
+ } catch (ManagedObjectNotFoundException e) {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_DANGLING_REFERENCE.get(ufn, name, getName());
+ unacceptableReasons.add(msg);
+ isAcceptable = false;
+ continue;
+ }
+
+ // Make sure the reference managed object is enabled.
+ if (needsEnabling) {
+ if (!targetIsEnabledCondition.evaluate(context, ref)) {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_TARGET_DISABLED.get(ufn, name, getName());
+ unacceptableReasons.add(msg);
+ isAcceptable = false;
+ }
+ }
+ }
+ return isAcceptable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isModifyAcceptable(ManagementContext context, ManagedObject<?> managedObject,
+ Collection<LocalizableMessage> unacceptableReasons) throws AuthorizationException, CommunicationException {
+ // The same constraint applies as for adds.
+ return isAddAcceptable(context, managedObject, unacceptableReasons);
+ }
+
+ }
+
+ /**
+ * The client-side constraint handler implementation which enforces
+ * referential integrity when aggregated managed objects are deleted or
+ * modified.
+ */
+ private class TargetClientHandler extends ClientConstraintHandler {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isDeleteAcceptable(ManagementContext context, ManagedObjectPath<?, ?> path,
+ Collection<LocalizableMessage> unacceptableReasons) throws AuthorizationException, CommunicationException {
+ // Any references to the deleted managed object should cause a
+ // constraint violation.
+ boolean isAcceptable = true;
+ for (ManagedObject<?> mo : findReferences(context, getManagedObjectDefinition(), path.getName())) {
+ String name = mo.getManagedObjectPath().getName();
+ if (name == null) {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_CANNOT_DELETE_WITHOUT_NAME.get(getName(), mo
+ .getManagedObjectDefinition().getUserFriendlyName(), getManagedObjectDefinition()
+ .getUserFriendlyName());
+ unacceptableReasons.add(msg);
+ } else {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_CANNOT_DELETE_WITH_NAME.get(getName(), mo
+ .getManagedObjectDefinition().getUserFriendlyName(), name, getManagedObjectDefinition()
+ .getUserFriendlyName());
+ unacceptableReasons.add(msg);
+ }
+ isAcceptable = false;
+ }
+ return isAcceptable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isModifyAcceptable(ManagementContext context, ManagedObject<?> managedObject,
+ Collection<LocalizableMessage> unacceptableReasons) throws AuthorizationException, CommunicationException {
+ // If the modified managed object is disabled and there are some
+ // active references then refuse the change.
+ if (targetIsEnabledCondition.evaluate(context, managedObject)) {
+ return true;
+ }
+
+ // The referenced managed object is disabled. Need to check for
+ // active references.
+ boolean isAcceptable = true;
+ for (ManagedObject<?> mo : findReferences(context, getManagedObjectDefinition(), managedObject
+ .getManagedObjectPath().getName())) {
+ if (targetNeedsEnablingCondition.evaluate(context, mo)) {
+ String name = mo.getManagedObjectPath().getName();
+ if (name == null) {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_CANNOT_DISABLE_WITHOUT_NAME.get(managedObject
+ .getManagedObjectDefinition().getUserFriendlyName(), getName(), mo
+ .getManagedObjectDefinition().getUserFriendlyName());
+ unacceptableReasons.add(msg);
+ } else {
+ LocalizableMessage msg = ERR_CLIENT_REFINT_CANNOT_DISABLE_WITH_NAME.get(managedObject
+ .getManagedObjectDefinition().getUserFriendlyName(), getName(), mo
+ .getManagedObjectDefinition().getUserFriendlyName(), name);
+ unacceptableReasons.add(msg);
+ }
+ isAcceptable = false;
+ }
+ }
+ return isAcceptable;
+ }
+
+ // Find all managed objects which reference the named managed
+ // object using this property.
+ private <CC extends ConfigurationClient> List<ManagedObject<? extends CC>> findReferences(
+ ManagementContext context, AbstractManagedObjectDefinition<CC, ?> mod, String name)
+ throws AuthorizationException, CommunicationException {
+ List<ManagedObject<? extends CC>> instances = findInstances(context, mod);
+
+ Iterator<ManagedObject<? extends CC>> i = instances.iterator();
+ while (i.hasNext()) {
+ ManagedObject<? extends CC> mo = i.next();
+ boolean hasReference = false;
+
+ for (String value : mo.getPropertyValues(AggregationPropertyDefinition.this)) {
+ if (compare(value, name) == 0) {
+ hasReference = true;
+ break;
+ }
+ }
+
+ if (!hasReference) {
+ i.remove();
+ }
+ }
+
+ return instances;
+ }
+
+ // Find all instances of a specific type of managed object.
+ @SuppressWarnings("unchecked")
+ private <CC extends ConfigurationClient> List<ManagedObject<? extends CC>> findInstances(
+ ManagementContext context, AbstractManagedObjectDefinition<CC, ?> mod) throws AuthorizationException,
+ CommunicationException {
+ List<ManagedObject<? extends CC>> instances = new LinkedList<ManagedObject<? extends CC>>();
+
+ if (mod == RootCfgDefn.getInstance()) {
+ instances.add((ManagedObject<? extends CC>) context.getRootConfigurationManagedObject());
+ } else {
+ for (RelationDefinition<? super CC, ?> rd : mod.getAllReverseRelationDefinitions()) {
+ for (ManagedObject<?> parent : findInstances(context, rd.getParentDefinition())) {
+ try {
+ if (rd instanceof SingletonRelationDefinition) {
+ SingletonRelationDefinition<? super CC, ?> srd = (SingletonRelationDefinition<? super CC, ?>) rd;
+ ManagedObject<?> mo = parent.getChild(srd);
+ if (mo.getManagedObjectDefinition().isChildOf(mod)) {
+ instances.add((ManagedObject<? extends CC>) mo);
+ }
+ } else if (rd instanceof OptionalRelationDefinition) {
+ OptionalRelationDefinition<? super CC, ?> ord = (OptionalRelationDefinition<? super CC, ?>) rd;
+ ManagedObject<?> mo = parent.getChild(ord);
+ if (mo.getManagedObjectDefinition().isChildOf(mod)) {
+ instances.add((ManagedObject<? extends CC>) mo);
+ }
+ } else if (rd instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<? super CC, ?> ird = (InstantiableRelationDefinition<? super CC, ?>) rd;
+
+ for (String name : parent.listChildren(ird)) {
+ ManagedObject<?> mo = parent.getChild(ird, name);
+ if (mo.getManagedObjectDefinition().isChildOf(mod)) {
+ instances.add((ManagedObject<? extends CC>) mo);
+ }
+ }
+ }
+ } catch (OperationsException e) {
+ // Ignore all operations exceptions.
+ }
+ }
+ }
+ }
+
+ return instances;
+ }
+ }
+
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+ /**
+ * Creates an aggregation property definition builder.
+ *
+ * @param <C>
+ * The type of client managed object configuration that this
+ * aggregation property definition refers to.
+ * @param <S>
+ * The type of server managed object configuration that this
+ * aggregation property definition refers to.
+ * @param d
+ * The managed object definition associated with this property
+ * definition.
+ * @param propertyName
+ * The property name.
+ * @return Returns the new aggregation property definition builder.
+ */
+ public static <C extends ConfigurationClient, S extends Configuration> Builder<C, S> createBuilder(
+ AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
+ return new Builder<C, S>(d, propertyName);
+ }
+
+ // The active server-side referential integrity change listeners
+ // associated with this property.
+ private final Map<DN, List<ReferentialIntegrityChangeListener>> changeListeners = new HashMap<DN, List<ReferentialIntegrityChangeListener>>();
+
+ // The active server-side referential integrity delete listeners
+ // associated with this property.
+ private final Map<DN, List<ReferentialIntegrityDeleteListener>> deleteListeners = new HashMap<DN, List<ReferentialIntegrityDeleteListener>>();
+
+ // The name of the managed object which is the parent of the
+ // aggregated managed objects.
+ private ManagedObjectPath<?, ?> parentPath;
// The string representation of the managed object path specifying
// the parent of the aggregated managed objects.
- private String parentPathString = null;
+ private final String parentPathString;
// The name of a relation in the parent managed object which
// contains the aggregated managed objects.
- private String rdName = null;
+ private final String rdName;
- // The condition which is used to determine if a referenced
- // managed object is enabled.
- private Condition targetIsEnabledCondition = Conditions.TRUE;
+ // The relation in the parent managed object which contains the
+ // aggregated managed objects.
+ private InstantiableRelationDefinition<C, S> relationDefinition;
+
+ // The source constraint.
+ private final Constraint sourceConstraint;
+
+ // The condition which is used to determine if a referenced managed
+ // object is enabled.
+ private final Condition targetIsEnabledCondition;
// The condition which is used to determine whether or not
// referenced managed objects need to be enabled.
- private Condition targetNeedsEnablingCondition = Conditions.TRUE;
+ private final Condition targetNeedsEnablingCondition;
+ // Private constructor.
+ private AggregationPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d, String propertyName,
+ EnumSet<PropertyOption> options, AdministratorAction adminAction,
+ DefaultBehaviorProvider<String> defaultBehavior, String parentPathString, String rdName,
+ Condition targetNeedsEnablingCondition, Condition targetIsEnabledCondition) {
+ super(d, String.class, propertyName, options, adminAction, defaultBehavior);
+ this.parentPathString = parentPathString;
+ this.rdName = rdName;
+ this.targetNeedsEnablingCondition = targetNeedsEnablingCondition;
+ this.targetIsEnabledCondition = targetIsEnabledCondition;
+ this.sourceConstraint = new Constraint() {
- // Private constructor
- private Builder(AbstractManagedObjectDefinition<?, ?> d,
- String propertyName) {
- super(d, propertyName);
- }
-
-
-
- /**
- * Sets the name of the managed object which is the parent of the
- * aggregated managed objects.
- * <p>
- * This must be defined before the property definition can be
- * built.
- *
- * @param pathString
- * The string representation of the managed object path
- * specifying the parent of the aggregated managed
- * objects.
- */
- public final void setParentPath(String pathString) {
- this.parentPathString = pathString;
- }
-
-
-
- /**
- * Sets the relation in the parent managed object which contains
- * the aggregated managed objects.
- * <p>
- * This must be defined before the property definition can be
- * built.
- *
- * @param rdName
- * The name of a relation in the parent managed object
- * which contains the aggregated managed objects.
- */
- public final void setRelationDefinition(String rdName) {
- this.rdName = rdName;
- }
-
-
-
- /**
- * Sets the condition which is used to determine if a referenced
- * managed object is enabled. By default referenced managed
- * objects are assumed to always be enabled.
- *
- * @param condition
- * The condition which is used to determine if a
- * referenced managed object is enabled.
- */
- public final void setTargetIsEnabledCondition(Condition condition) {
- this.targetIsEnabledCondition = condition;
- }
-
-
-
- /**
- * Sets the condition which is used to determine whether or not
- * referenced managed objects need to be enabled. By default
- * referenced managed objects must always be enabled.
- *
- * @param condition
- * The condition which is used to determine whether or
- * not referenced managed objects need to be enabled.
- */
- public final void setTargetNeedsEnablingCondition(Condition condition) {
- this.targetNeedsEnablingCondition = condition;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected AggregationPropertyDefinition<C, S> buildInstance(
- AbstractManagedObjectDefinition<?, ?> d, String propertyName,
- EnumSet<PropertyOption> options, AdministratorAction adminAction,
- DefaultBehaviorProvider<String> defaultBehavior) {
- // Make sure that the parent path has been defined.
- if (parentPathString == null) {
- throw new IllegalStateException("Parent path undefined");
- }
-
- // Make sure that the relation definition has been defined.
- if (rdName == null) {
- throw new IllegalStateException("Relation definition undefined");
- }
-
- return new AggregationPropertyDefinition<C, S>(d, propertyName, options,
- adminAction, defaultBehavior, parentPathString, rdName,
- targetNeedsEnablingCondition, targetIsEnabledCondition);
- }
-
- }
-
-
-
- /**
- * A change listener which prevents the named component from being
- * disabled.
- */
- private class ReferentialIntegrityChangeListener implements
- ServerManagedObjectChangeListener<S> {
-
- // The error message which should be returned if an attempt is
- // made to disable the referenced component.
- private final Message message;
-
- // The path of the referenced component.
- private final ManagedObjectPath<C, S> path;
-
-
-
- // Creates a new referential integrity delete listener.
- private ReferentialIntegrityChangeListener(ManagedObjectPath<C, S> path,
- Message message) {
- this.path = path;
- this.message = message;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationChange(
- ServerManagedObject<? extends S> mo) {
- try {
- if (targetIsEnabledCondition.evaluate(mo)) {
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
- } catch (ConfigException e) {
- // This should not happen - ignore it and throw an exception
- // anyway below.
- }
-
- // This should not happen - the previous call-back should have
- // trapped this.
- throw new IllegalStateException("Attempting to disable a referenced "
- + relationDefinition.getChildDefinition().getUserFriendlyName());
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public boolean isConfigurationChangeAcceptable(
- ServerManagedObject<? extends S> mo,
- List<Message> unacceptableReasons) {
- // Always prevent the referenced component from being
- // disabled.
- try {
- if (!targetIsEnabledCondition.evaluate(mo)) {
- unacceptableReasons.add(message);
- return false;
- } else {
- return true;
- }
- } catch (ConfigException e) {
- // The condition could not be evaluated.
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- Message message = ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION.get(mo
- .getManagedObjectDefinition().getUserFriendlyName(), String
- .valueOf(mo.getDN()), StaticUtils.getExceptionMessage(e));
- ErrorLogger.logError(message);
- unacceptableReasons.add(message);
- return false;
- }
- }
-
-
-
- // Gets the path associated with this listener.
- private ManagedObjectPath<C, S> getManagedObjectPath() {
- return path;
- }
-
- }
-
-
-
- /**
- * A delete listener which prevents the named component from being
- * deleted.
- */
- private class ReferentialIntegrityDeleteListener implements
- ConfigurationDeleteListener<S> {
-
- // The DN of the referenced configuration entry.
- private final DN dn;
-
- // The error message which should be returned if an attempt is
- // made to delete the referenced component.
- private final Message message;
-
-
-
- // Creates a new referential integrity delete listener.
- private ReferentialIntegrityDeleteListener(DN dn, Message message) {
- this.dn = dn;
- this.message = message;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationDelete(S configuration) {
- // This should not happen - the
- // isConfigurationDeleteAcceptable() call-back should have
- // trapped this.
- if (configuration.dn().equals(dn)) {
- // This should not happen - the
- // isConfigurationDeleteAcceptable() call-back should have
- // trapped this.
- throw new IllegalStateException("Attempting to delete a referenced "
- + relationDefinition.getChildDefinition().getUserFriendlyName());
- } else {
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public boolean isConfigurationDeleteAcceptable(S configuration,
- List<Message> unacceptableReasons) {
- if (configuration.dn().equals(dn)) {
- // Always prevent deletion of the referenced component.
- unacceptableReasons.add(message);
- return false;
- }
-
- return true;
- }
-
- }
-
-
-
- /**
- * The server-side constraint handler implementation.
- */
- private class ServerHandler extends ServerConstraintHandler {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isUsable(ServerManagedObject<?> managedObject,
- Collection<Message> unacceptableReasons) throws ConfigException {
- SortedSet<String> names = managedObject
- .getPropertyValues(AggregationPropertyDefinition.this);
- ServerManagementContext context = ServerManagementContext.getInstance();
- Message thisUFN = managedObject.getManagedObjectDefinition()
- .getUserFriendlyName();
- String thisDN = managedObject.getDN().toString();
- Message thatUFN = getRelationDefinition().getUserFriendlyName();
-
- boolean isUsable = true;
- boolean needsEnabling = targetNeedsEnablingCondition
- .evaluate(managedObject);
- for (String name : names) {
- ManagedObjectPath<C, S> path = getChildPath(name);
- String thatDN = path.toDN().toString();
-
- if (!context.managedObjectExists(path)) {
- Message msg = ERR_SERVER_REFINT_DANGLING_REFERENCE.get(name,
- getName(), thisUFN, thisDN, thatUFN, thatDN);
- unacceptableReasons.add(msg);
- isUsable = false;
- } else if (needsEnabling) {
- // Check that the referenced component is enabled if
- // required.
- ServerManagedObject<? extends S> ref = context.getManagedObject(path);
- if (!targetIsEnabledCondition.evaluate(ref)) {
- Message msg = ERR_SERVER_REFINT_TARGET_DISABLED.get(name,
- getName(), thisUFN, thisDN, thatUFN, thatDN);
- unacceptableReasons.add(msg);
- isUsable = false;
- }
- }
- }
-
- return isUsable;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void performPostAdd(ServerManagedObject<?> managedObject)
- throws ConfigException {
- // First make sure existing listeners associated with this
- // managed object are removed. This is required in order to
- // prevent multiple change listener registrations from
- // occurring, for example if this call-back is invoked multiple
- // times after the same add event.
- performPostDelete(managedObject);
-
- // Add change and delete listeners against all referenced
- // components.
- Message thisUFN = managedObject.getManagedObjectDefinition()
- .getUserFriendlyName();
- String thisDN = managedObject.getDN().toString();
- Message thatUFN = getRelationDefinition().getUserFriendlyName();
-
- // Referenced managed objects will only need a change listener
- // if they have can be disabled.
- boolean needsChangeListeners = targetNeedsEnablingCondition
- .evaluate(managedObject);
-
- // Delete listeners need to be registered against the parent
- // entry of the referenced components.
- ServerManagementContext context = ServerManagementContext.getInstance();
- ManagedObjectPath<?, ?> parentPath = getParentPath();
- ServerManagedObject<?> parent = context.getManagedObject(parentPath);
-
- // Create entries in the listener tables.
- List<ReferentialIntegrityDeleteListener> dlist =
- new LinkedList<ReferentialIntegrityDeleteListener>();
- deleteListeners.put(managedObject.getDN(), dlist);
-
- List<ReferentialIntegrityChangeListener> clist =
- new LinkedList<ReferentialIntegrityChangeListener>();
- changeListeners.put(managedObject.getDN(), clist);
-
- for (String name : managedObject
- .getPropertyValues(AggregationPropertyDefinition.this)) {
- ManagedObjectPath<C, S> path = getChildPath(name);
- DN dn = path.toDN();
- String thatDN = dn.toString();
-
- // Register the delete listener.
- Message msg = ERR_SERVER_REFINT_CANNOT_DELETE.get(thatUFN, thatDN,
- getName(), thisUFN, thisDN);
- ReferentialIntegrityDeleteListener dl =
- new ReferentialIntegrityDeleteListener(dn, msg);
- parent.registerDeleteListener(getRelationDefinition(), dl);
- dlist.add(dl);
-
- // Register the change listener if required.
- if (needsChangeListeners) {
- ServerManagedObject<? extends S> ref = context.getManagedObject(path);
- msg = ERR_SERVER_REFINT_CANNOT_DISABLE.get(thatUFN, thatDN,
- getName(), thisUFN, thisDN);
- ReferentialIntegrityChangeListener cl =
- new ReferentialIntegrityChangeListener(path, msg);
- ref.registerChangeListener(cl);
- clist.add(cl);
- }
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void performPostDelete(ServerManagedObject<?> managedObject)
- throws ConfigException {
- // Remove any registered delete and change listeners.
- ServerManagementContext context = ServerManagementContext.getInstance();
- DN dn = managedObject.getDN();
-
- // Delete listeners need to be deregistered against the parent
- // entry of the referenced components.
- ManagedObjectPath<?, ?> parentPath = getParentPath();
- ServerManagedObject<?> parent = context.getManagedObject(parentPath);
- if (deleteListeners.containsKey(dn)) {
- for (ReferentialIntegrityDeleteListener dl : deleteListeners.get(dn)) {
- parent.deregisterDeleteListener(getRelationDefinition(), dl);
- }
- deleteListeners.remove(dn);
- }
-
- // Change listeners need to be deregistered from their
- // associated referenced component.
- if (changeListeners.containsKey(dn)) {
- for (ReferentialIntegrityChangeListener cl : changeListeners.get(dn)) {
- ManagedObjectPath<C, S> path = cl.getManagedObjectPath();
- ServerManagedObject<? extends S> ref = context.getManagedObject(path);
- ref.deregisterChangeListener(cl);
- }
- changeListeners.remove(dn);
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void performPostModify(ServerManagedObject<?> managedObject)
- throws ConfigException {
- // Remove all the constraints associated with this managed
- // object and then re-register them.
- performPostDelete(managedObject);
- performPostAdd(managedObject);
- }
- }
-
-
-
- /**
- * The client-side constraint handler implementation which enforces
- * referential integrity when aggregating managed objects are added
- * or modified.
- */
- private class SourceClientHandler extends ClientConstraintHandler {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isAddAcceptable(ManagementContext context,
- ManagedObject<?> managedObject, Collection<Message> unacceptableReasons)
- throws AuthorizationException, CommunicationException {
- // If all of this managed object's "enabled" properties are true
- // then any referenced managed objects must also be enabled.
- boolean needsEnabling = targetNeedsEnablingCondition.evaluate(context,
- managedObject);
-
- // Check the referenced managed objects exist and, if required,
- // are enabled.
- boolean isAcceptable = true;
- Message ufn = getRelationDefinition().getUserFriendlyName();
- for (String name : managedObject
- .getPropertyValues(AggregationPropertyDefinition.this)) {
- // Retrieve the referenced managed object and make sure it
- // exists.
- ManagedObjectPath<?, ?> path = getChildPath(name);
- ManagedObject<?> ref;
- try {
- ref = context.getManagedObject(path);
- } catch (DefinitionDecodingException e) {
- Message msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name,
- getName(), e.getMessageObject());
- unacceptableReasons.add(msg);
- isAcceptable = false;
- continue;
- } catch (ManagedObjectDecodingException e) {
- Message msg = ERR_CLIENT_REFINT_TARGET_INVALID.get(ufn, name,
- getName(), e.getMessageObject());
- unacceptableReasons.add(msg);
- isAcceptable = false;
- continue;
- } catch (ManagedObjectNotFoundException e) {
- Message msg = ERR_CLIENT_REFINT_TARGET_DANGLING_REFERENCE.get(ufn,
- name, getName());
- unacceptableReasons.add(msg);
- isAcceptable = false;
- continue;
- }
-
- // Make sure the reference managed object is enabled.
- if (needsEnabling) {
- if (!targetIsEnabledCondition.evaluate(context, ref)) {
- Message msg = ERR_CLIENT_REFINT_TARGET_DISABLED.get(ufn, name,
- getName());
- unacceptableReasons.add(msg);
- isAcceptable = false;
- }
- }
- }
- return isAcceptable;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isModifyAcceptable(ManagementContext context,
- ManagedObject<?> managedObject, Collection<Message> unacceptableReasons)
- throws AuthorizationException, CommunicationException {
- // The same constraint applies as for adds.
- return isAddAcceptable(context, managedObject, unacceptableReasons);
- }
-
- }
-
-
-
- /**
- * The client-side constraint handler implementation which enforces
- * referential integrity when aggregated managed objects are deleted
- * or modified.
- */
- private class TargetClientHandler extends ClientConstraintHandler {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isDeleteAcceptable(ManagementContext context,
- ManagedObjectPath<?, ?> path, Collection<Message> unacceptableReasons)
- throws AuthorizationException, CommunicationException {
- // Any references to the deleted managed object should cause a
- // constraint violation.
- boolean isAcceptable = true;
- for (ManagedObject<?> mo : findReferences(context,
- getManagedObjectDefinition(), path.getName())) {
- String name = mo.getManagedObjectPath().getName();
- if (name == null) {
- Message msg = ERR_CLIENT_REFINT_CANNOT_DELETE_WITHOUT_NAME.get(
- getName(), mo.getManagedObjectDefinition().getUserFriendlyName(),
- getManagedObjectDefinition().getUserFriendlyName());
- unacceptableReasons.add(msg);
- } else {
- Message msg = ERR_CLIENT_REFINT_CANNOT_DELETE_WITH_NAME.get(
- getName(), mo.getManagedObjectDefinition().getUserFriendlyName(),
- name, getManagedObjectDefinition().getUserFriendlyName());
- unacceptableReasons.add(msg);
- }
- isAcceptable = false;
- }
- return isAcceptable;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean isModifyAcceptable(ManagementContext context,
- ManagedObject<?> managedObject, Collection<Message> unacceptableReasons)
- throws AuthorizationException, CommunicationException {
- // If the modified managed object is disabled and there are some
- // active references then refuse the change.
- if (targetIsEnabledCondition.evaluate(context, managedObject)) {
- return true;
- }
-
- // The referenced managed object is disabled. Need to check for
- // active references.
- boolean isAcceptable = true;
- for (ManagedObject<?> mo : findReferences(context,
- getManagedObjectDefinition(), managedObject.getManagedObjectPath()
- .getName())) {
- if (targetNeedsEnablingCondition.evaluate(context, mo)) {
- String name = mo.getManagedObjectPath().getName();
- if (name == null) {
- Message msg = ERR_CLIENT_REFINT_CANNOT_DISABLE_WITHOUT_NAME.get(
- managedObject.getManagedObjectDefinition()
- .getUserFriendlyName(), getName(), mo
- .getManagedObjectDefinition().getUserFriendlyName());
- unacceptableReasons.add(msg);
- } else {
- Message msg = ERR_CLIENT_REFINT_CANNOT_DISABLE_WITH_NAME.get(
- managedObject.getManagedObjectDefinition()
- .getUserFriendlyName(), getName(), mo
- .getManagedObjectDefinition().getUserFriendlyName(), name);
- unacceptableReasons.add(msg);
- }
- isAcceptable = false;
- }
- }
- return isAcceptable;
- }
-
-
-
- // Find all managed objects which reference the named managed
- // object using this property.
- private <CC extends ConfigurationClient>
- List<ManagedObject<? extends CC>> findReferences(
- ManagementContext context, AbstractManagedObjectDefinition<CC, ?> mod,
- String name) throws AuthorizationException, CommunicationException {
- List<ManagedObject<? extends CC>> instances = findInstances(context, mod);
-
- Iterator<ManagedObject<? extends CC>> i = instances.iterator();
- while (i.hasNext()) {
- ManagedObject<? extends CC> mo = i.next();
- boolean hasReference = false;
-
- for (String value : mo
- .getPropertyValues(AggregationPropertyDefinition.this)) {
- if (compare(value, name) == 0) {
- hasReference = true;
- break;
- }
- }
-
- if (!hasReference) {
- i.remove();
- }
- }
-
- return instances;
- }
-
-
-
- // Find all instances of a specific type of managed object.
- @SuppressWarnings("unchecked")
- private <CC extends ConfigurationClient>
- List<ManagedObject<? extends CC>> findInstances(
- ManagementContext context, AbstractManagedObjectDefinition<CC, ?> mod)
- throws AuthorizationException, CommunicationException {
- List<ManagedObject<? extends CC>> instances =
- new LinkedList<ManagedObject<? extends CC>>();
-
- if (mod == RootCfgDefn.getInstance()) {
- instances.add((ManagedObject<? extends CC>) context
- .getRootConfigurationManagedObject());
- } else {
- for (RelationDefinition<? super CC, ?> rd : mod
- .getAllReverseRelationDefinitions()) {
- for (ManagedObject<?> parent : findInstances(context, rd
- .getParentDefinition())) {
- try {
- if (rd instanceof SingletonRelationDefinition) {
- SingletonRelationDefinition<? super CC, ?> srd =
- (SingletonRelationDefinition<? super CC, ?>) rd;
- ManagedObject<?> mo = parent.getChild(srd);
- if (mo.getManagedObjectDefinition().isChildOf(mod)) {
- instances.add((ManagedObject<? extends CC>) mo);
- }
- } else if (rd instanceof OptionalRelationDefinition) {
- OptionalRelationDefinition<? super CC, ?> ord =
- (OptionalRelationDefinition<? super CC, ?>) rd;
- ManagedObject<?> mo = parent.getChild(ord);
- if (mo.getManagedObjectDefinition().isChildOf(mod)) {
- instances.add((ManagedObject<? extends CC>) mo);
- }
- } else if (rd instanceof InstantiableRelationDefinition) {
- InstantiableRelationDefinition<? super CC, ?> ird =
- (InstantiableRelationDefinition<? super CC, ?>) rd;
-
- for (String name : parent.listChildren(ird)) {
- ManagedObject<?> mo = parent.getChild(ird, name);
- if (mo.getManagedObjectDefinition().isChildOf(mod)) {
- instances.add((ManagedObject<? extends CC>) mo);
- }
- }
- }
- } catch (OperationsException e) {
- // Ignore all operations exceptions.
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
+ ClientConstraintHandler handler = new SourceClientHandler();
+ return Collections.singleton(handler);
}
- }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
+ ServerConstraintHandler handler = new ServerHandler();
+ return Collections.singleton(handler);
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) {
+ return v.visitAggregation(this, p);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <R, P> R accept(PropertyValueVisitor<R, P> v, String value, P p) {
+ return v.visitAggregation(this, value, p);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String decodeValue(String value) throws IllegalPropertyValueStringException {
+ ensureNotNull(value);
+
+ try {
+ validateValue(value);
+ return value;
+ } catch (IllegalPropertyValueException e) {
+ throw new IllegalPropertyValueStringException(this, value);
}
- }
-
- return instances;
}
- }
-
-
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
-
-
- /**
- * Creates an aggregation property definition builder.
- *
- * @param <C>
- * The type of client managed object configuration that
- * this aggregation property definition refers to.
- * @param <S>
- * The type of server managed object configuration that
- * this aggregation property definition refers to.
- * @param d
- * The managed object definition associated with this
- * property definition.
- * @param propertyName
- * The property name.
- * @return Returns the new aggregation property definition builder.
- */
- public static <C extends ConfigurationClient, S extends Configuration>
- Builder<C, S> createBuilder(
- AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
- return new Builder<C, S>(d, propertyName);
- }
-
- // The active server-side referential integrity change listeners
- // associated with this property.
- private final Map<DN, List<ReferentialIntegrityChangeListener>>
- changeListeners = new HashMap<DN,
- List<ReferentialIntegrityChangeListener>>();
-
- // The active server-side referential integrity delete listeners
- // associated with this property.
- private final Map<DN, List<ReferentialIntegrityDeleteListener>>
- deleteListeners = new HashMap<DN,
- List<ReferentialIntegrityDeleteListener>>();
-
- // The name of the managed object which is the parent of the
- // aggregated managed objects.
- private ManagedObjectPath<?, ?> parentPath;
-
- // The string representation of the managed object path specifying
- // the parent of the aggregated managed objects.
- private final String parentPathString;
-
- // The name of a relation in the parent managed object which
- // contains the aggregated managed objects.
- private final String rdName;
-
- // The relation in the parent managed object which contains the
- // aggregated managed objects.
- private InstantiableRelationDefinition<C, S> relationDefinition;
-
- // The source constraint.
- private final Constraint sourceConstraint;
-
- // The condition which is used to determine if a referenced managed
- // object is enabled.
- private final Condition targetIsEnabledCondition;
-
- // The condition which is used to determine whether or not
- // referenced managed objects need to be enabled.
- private final Condition targetNeedsEnablingCondition;
-
-
-
- // Private constructor.
- private AggregationPropertyDefinition(
- AbstractManagedObjectDefinition<?, ?> d, String propertyName,
- EnumSet<PropertyOption> options, AdministratorAction adminAction,
- DefaultBehaviorProvider<String> defaultBehavior, String parentPathString,
- String rdName, Condition targetNeedsEnablingCondition,
- Condition targetIsEnabledCondition) {
- super(d, String.class, propertyName, options, adminAction, defaultBehavior);
-
- this.parentPathString = parentPathString;
- this.rdName = rdName;
- this.targetNeedsEnablingCondition = targetNeedsEnablingCondition;
- this.targetIsEnabledCondition = targetIsEnabledCondition;
- this.sourceConstraint = new Constraint() {
-
- /**
- * {@inheritDoc}
- */
- public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
- ClientConstraintHandler handler = new SourceClientHandler();
- return Collections.singleton(handler);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
- ServerConstraintHandler handler = new ServerHandler();
- return Collections.singleton(handler);
- }
- };
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) {
- return v.visitAggregation(this, p);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <R, P> R accept(PropertyValueVisitor<R, P> v, String value, P p) {
- return v.visitAggregation(this, value, p);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String decodeValue(String value)
- throws IllegalPropertyValueStringException {
- ensureNotNull(value);
-
- try {
- validateValue(value);
- return value;
- } catch (IllegalPropertyValueException e) {
- throw new IllegalPropertyValueStringException(this, value);
+ /**
+ * Constructs a DN for a referenced managed object having the provided name.
+ * This method is implemented by first calling {@link #getChildPath(String)}
+ * and then invoking {@code ManagedObjectPath.toDN()} on the returned path.
+ *
+ * @param name
+ * The name of the child managed object.
+ * @return Returns a DN for a referenced managed object having the provided
+ * name.
+ */
+ public final DN getChildDN(String name) {
+ return getChildPath(name).toDN();
}
- }
-
-
- /**
- * Constructs a DN for a referenced managed object having the
- * provided name. This method is implemented by first calling
- * {@link #getChildPath(String)} and then invoking
- * {@code ManagedObjectPath.toDN()} on the returned path.
- *
- * @param name
- * The name of the child managed object.
- * @return Returns a DN for a referenced managed object having the
- * provided name.
- */
- public final DN getChildDN(String name) {
- return getChildPath(name).toDN();
- }
-
-
-
- /**
- * Constructs a managed object path for a referenced managed object
- * having the provided name.
- *
- * @param name
- * The name of the child managed object.
- * @return Returns a managed object path for a referenced managed
- * object having the provided name.
- */
- public final ManagedObjectPath<C, S> getChildPath(String name) {
- return parentPath.child(relationDefinition, name);
- }
-
-
-
- /**
- * Gets the name of the managed object which is the parent of the
- * aggregated managed objects.
- *
- * @return Returns the name of the managed object which is the
- * parent of the aggregated managed objects.
- */
- public final ManagedObjectPath<?, ?> getParentPath() {
- return parentPath;
- }
-
-
-
- /**
- * Gets the relation in the parent managed object which contains the
- * aggregated managed objects.
- *
- * @return Returns the relation in the parent managed object which
- * contains the aggregated managed objects.
- */
- public final InstantiableRelationDefinition<C, S> getRelationDefinition() {
- return relationDefinition;
- }
-
-
-
- /**
- * Gets the constraint which should be enforced on the aggregating
- * managed object.
- *
- * @return Returns the constraint which should be enforced on the
- * aggregating managed object.
- */
- public final Constraint getSourceConstraint() {
- return sourceConstraint;
- }
-
-
-
- /**
- * Gets the optional constraint synopsis of this aggregation
- * property definition in the default locale. The constraint
- * synopsis describes when and how referenced managed objects must
- * be enabled. When there are no constraints between the source
- * managed object and the objects it references through this
- * aggregation, <code>null</code> is returned.
- *
- * @return Returns the optional constraint synopsis of this
- * aggregation property definition in the default locale, or
- * <code>null</code> if there is no constraint synopsis.
- */
- public final Message getSourceConstraintSynopsis() {
- return getSourceConstraintSynopsis(Locale.getDefault());
- }
-
-
-
- /**
- * Gets the optional constraint synopsis of this aggregation
- * property definition in the specified locale.The constraint
- * synopsis describes when and how referenced managed objects must
- * be enabled. When there are no constraints between the source
- * managed object and the objects it references through this
- * aggregation, <code>null</code> is returned.
- *
- * @param locale
- * The locale.
- * @return Returns the optional constraint synopsis of this
- * aggregation property definition in the specified locale,
- * or <code>null</code> if there is no constraint
- * synopsis.
- */
- public final Message getSourceConstraintSynopsis(Locale locale) {
- ManagedObjectDefinitionI18NResource resource =
- ManagedObjectDefinitionI18NResource.getInstance();
- String property = "property." + getName()
- + ".syntax.aggregation.constraint-synopsis";
- try {
- return resource
- .getMessage(getManagedObjectDefinition(), property, locale);
- } catch (MissingResourceException e) {
- return null;
+ /**
+ * Constructs a managed object path for a referenced managed object having
+ * the provided name.
+ *
+ * @param name
+ * The name of the child managed object.
+ * @return Returns a managed object path for a referenced managed object
+ * having the provided name.
+ */
+ public final ManagedObjectPath<C, S> getChildPath(String name) {
+ return parentPath.child(relationDefinition, name);
}
- }
-
-
- /**
- * Gets the condition which is used to determine if a referenced
- * managed object is enabled.
- *
- * @return Returns the condition which is used to determine if a
- * referenced managed object is enabled.
- */
- public final Condition getTargetIsEnabledCondition() {
- return targetIsEnabledCondition;
- }
-
-
-
- /**
- * Gets the condition which is used to determine whether or not
- * referenced managed objects need to be enabled.
- *
- * @return Returns the condition which is used to determine whether
- * or not referenced managed objects need to be enabled.
- */
- public final Condition getTargetNeedsEnablingCondition() {
- return targetNeedsEnablingCondition;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String normalizeValue(String value)
- throws IllegalPropertyValueException {
- try {
- Reference<C, S> reference = Reference.parseName(parentPath,
- relationDefinition, value);
- return reference.getNormalizedName();
- } catch (IllegalArgumentException e) {
- throw new IllegalPropertyValueException(this, value);
+ /**
+ * Gets the name of the managed object which is the parent of the aggregated
+ * managed objects.
+ *
+ * @return Returns the name of the managed object which is the parent of the
+ * aggregated managed objects.
+ */
+ public final ManagedObjectPath<?, ?> getParentPath() {
+ return parentPath;
}
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void toString(StringBuilder builder) {
- super.toString(builder);
-
- builder.append(" parentPath=");
- builder.append(parentPath);
-
- builder.append(" relationDefinition=");
- builder.append(relationDefinition.getName());
-
- builder.append(" targetNeedsEnablingCondition=");
- builder.append(String.valueOf(targetNeedsEnablingCondition));
-
- builder.append(" targetIsEnabledCondition=");
- builder.append(String.valueOf(targetIsEnabledCondition));
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void validateValue(String value) throws IllegalPropertyValueException {
- try {
- Reference.parseName(parentPath, relationDefinition, value);
- } catch (IllegalArgumentException e) {
- throw new IllegalPropertyValueException(this, value);
+ /**
+ * Gets the relation in the parent managed object which contains the
+ * aggregated managed objects.
+ *
+ * @return Returns the relation in the parent managed object which contains
+ * the aggregated managed objects.
+ */
+ public final InstantiableRelationDefinition<C, S> getRelationDefinition() {
+ return relationDefinition;
}
- }
+ /**
+ * Gets the constraint which should be enforced on the aggregating managed
+ * object.
+ *
+ * @return Returns the constraint which should be enforced on the
+ * aggregating managed object.
+ */
+ public final Constraint getSourceConstraint() {
+ return sourceConstraint;
+ }
+ /**
+ * Gets the optional constraint synopsis of this aggregation property
+ * definition in the default locale. The constraint synopsis describes when
+ * and how referenced managed objects must be enabled. When there are no
+ * constraints between the source managed object and the objects it
+ * references through this aggregation, <code>null</code> is returned.
+ *
+ * @return Returns the optional constraint synopsis of this aggregation
+ * property definition in the default locale, or <code>null</code>
+ * if there is no constraint synopsis.
+ */
+ public final LocalizableMessage getSourceConstraintSynopsis() {
+ return getSourceConstraintSynopsis(Locale.getDefault());
+ }
- /**
- * {@inheritDoc}
- */
- @SuppressWarnings("unchecked")
- @Override
- public void initialize() throws Exception {
- // Decode the path.
- parentPath = ManagedObjectPath.valueOf(parentPathString);
+ /**
+ * Gets the optional constraint synopsis of this aggregation property
+ * definition in the specified locale.The constraint synopsis describes when
+ * and how referenced managed objects must be enabled. When there are no
+ * constraints between the source managed object and the objects it
+ * references through this aggregation, <code>null</code> is returned.
+ *
+ * @param locale
+ * The locale.
+ * @return Returns the optional constraint synopsis of this aggregation
+ * property definition in the specified locale, or <code>null</code>
+ * if there is no constraint synopsis.
+ */
+ public final LocalizableMessage getSourceConstraintSynopsis(Locale locale) {
+ ManagedObjectDefinitionI18NResource resource = ManagedObjectDefinitionI18NResource.getInstance();
+ String property = "property." + getName() + ".syntax.aggregation.constraint-synopsis";
+ try {
+ return resource.getLocalizableMessage(getManagedObjectDefinition(), property, locale);
+ } catch (MissingResourceException e) {
+ return null;
+ }
+ }
- // Decode the relation definition.
- AbstractManagedObjectDefinition<?, ?> parent = parentPath
- .getManagedObjectDefinition();
- RelationDefinition<?, ?> rd = parent.getRelationDefinition(rdName);
- relationDefinition = (InstantiableRelationDefinition<C, S>) rd;
+ /**
+ * Gets the condition which is used to determine if a referenced managed
+ * object is enabled.
+ *
+ * @return Returns the condition which is used to determine if a referenced
+ * managed object is enabled.
+ */
+ public final Condition getTargetIsEnabledCondition() {
+ return targetIsEnabledCondition;
+ }
- // Now decode the conditions.
- targetNeedsEnablingCondition.initialize(getManagedObjectDefinition());
- targetIsEnabledCondition.initialize(rd.getChildDefinition());
+ /**
+ * Gets the condition which is used to determine whether or not referenced
+ * managed objects need to be enabled.
+ *
+ * @return Returns the condition which is used to determine whether or not
+ * referenced managed objects need to be enabled.
+ */
+ public final Condition getTargetNeedsEnablingCondition() {
+ return targetNeedsEnablingCondition;
+ }
- // Register a client-side constraint with the referenced
- // definition. This will be used to enforce referential integrity
- // for actions performed against referenced managed objects.
- Constraint constraint = new Constraint() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String normalizeValue(String value) throws IllegalPropertyValueException {
+ try {
+ Reference<C, S> reference = Reference.parseName(parentPath, relationDefinition, value);
+ return reference.getNormalizedName();
+ } catch (IllegalArgumentException e) {
+ throw new IllegalPropertyValueException(this, value);
+ }
+ }
- /**
- * {@inheritDoc}
- */
- public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
- ClientConstraintHandler handler = new TargetClientHandler();
- return Collections.singleton(handler);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void toString(StringBuilder builder) {
+ super.toString(builder);
+ builder.append(" parentPath=");
+ builder.append(parentPath);
+ builder.append(" relationDefinition=");
+ builder.append(relationDefinition.getName());
- /**
- * {@inheritDoc}
- */
- public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
- return Collections.emptyList();
- }
- };
+ builder.append(" targetNeedsEnablingCondition=");
+ builder.append(String.valueOf(targetNeedsEnablingCondition));
- rd.getChildDefinition().registerConstraint(constraint);
- }
+ builder.append(" targetIsEnabledCondition=");
+ builder.append(String.valueOf(targetIsEnabledCondition));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void validateValue(String value) throws IllegalPropertyValueException {
+ try {
+ Reference.parseName(parentPath, relationDefinition, value);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalPropertyValueException(this, value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void initialize() throws Exception {
+ // Decode the path.
+ parentPath = ManagedObjectPath.valueOf(parentPathString);
+
+ // Decode the relation definition.
+ AbstractManagedObjectDefinition<?, ?> parent = parentPath.getManagedObjectDefinition();
+ RelationDefinition<?, ?> rd = parent.getRelationDefinition(rdName);
+ relationDefinition = (InstantiableRelationDefinition<C, S>) rd;
+
+ // Now decode the conditions.
+ targetNeedsEnablingCondition.initialize(getManagedObjectDefinition());
+ targetIsEnabledCondition.initialize(rd.getChildDefinition());
+
+ // Register a client-side constraint with the referenced
+ // definition. This will be used to enforce referential integrity
+ // for actions performed against referenced managed objects.
+ Constraint constraint = new Constraint() {
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
+ ClientConstraintHandler handler = new TargetClientHandler();
+ return Collections.singleton(handler);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
+ return Collections.emptyList();
+ }
+ };
+
+ rd.getChildDefinition().registerConstraint(constraint);
+ }
}
--
Gitblit v1.10.0