From 45359adc09ac1d9e48206c549e667ed6965c7cd3 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Mon, 28 May 2007 15:31:13 +0000
Subject: [PATCH] Fix the following issues:
---
opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java | 799 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 524 insertions(+), 275 deletions(-)
diff --git a/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java b/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
index d2f3d56..a0a5bfc 100644
--- a/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
+++ b/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -51,18 +51,22 @@
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
+import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AliasDefaultBehaviorProvider;
import org.opends.server.admin.ConfigurationClient;
+import org.opends.server.admin.DefaultBehaviorException;
+import org.opends.server.admin.DefaultBehaviorProviderVisitor;
+import org.opends.server.admin.DefinedDefaultBehaviorProvider;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.DefinitionResolver;
import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
+import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
import org.opends.server.admin.OptionalRelationDefinition;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.PropertyException;
@@ -70,16 +74,18 @@
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.admin.PropertyIsSingleValuedException;
import org.opends.server.admin.PropertyNotFoundException;
-import org.opends.server.admin.PropertyProvider;
+import org.opends.server.admin.PropertyOption;
import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
import org.opends.server.admin.SingletonRelationDefinition;
-import org.opends.server.admin.StringPropertyProvider;
+import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.admin.DefinitionDecodingException.Reason;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.client.Property;
import org.opends.server.admin.client.PropertySet;
@@ -99,31 +105,66 @@
ManagedObject<C> {
/**
- * Internal inherited default value provider implementation.
+ * A default behavior visitor used for retrieving the default values
+ * of a property.
+ *
+ * @param <T>
+ * The type of the property.
*/
- private static class MyInheritedDefaultValueProvider implements
- InheritedDefaultValueProvider {
+ private static class DefaultValueFinder<T> implements
+ DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> {
+
+ /**
+ * Get the default values for the specified property.
+ *
+ * @param <T>
+ * The type of the property.
+ * @param context
+ * The LDAP management context.
+ * @param p
+ * The managed object path of the current managed object.
+ * @param pd
+ * The property definition.
+ * @return Returns the default values for the specified property.
+ * @throws DefaultBehaviorException
+ * If the default values could not be retrieved or
+ * decoded properly.
+ */
+ public static <T> Collection<T> getDefaultValues(
+ LDAPManagementContext context, ManagedObjectPath p,
+ PropertyDefinition<T> pd) throws DefaultBehaviorException {
+ DefaultValueFinder<T> v = new DefaultValueFinder<T>(context, pd);
+ Collection<T> values = pd.getDefaultBehaviorProvider().accept(v, p);
+
+ if (v.exception != null) {
+ throw v.exception;
+ }
+
+ if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ throw new DefaultBehaviorException(pd,
+ new PropertyIsSingleValuedException(pd));
+ }
+
+ return values;
+ }
// The LDAP management context.
private final LDAPManagementContext context;
- // The base path.
- private final ManagedObjectPath path;
+ // Any exception that occurred whilst retrieving inherited default
+ // values.
+ private DefaultBehaviorException exception = null;
+
+ // The property definition whose default values are required.
+ private final PropertyDefinition<T> pd;
- /**
- * Create a new inherited default value provider.
- *
- * @param context
- * The LDAP management context.
- * @param path
- * The base path.
- */
- public MyInheritedDefaultValueProvider(LDAPManagementContext context,
- ManagedObjectPath path) {
+ // Private constructor.
+ private DefaultValueFinder(LDAPManagementContext context,
+ PropertyDefinition<T> pd) {
this.context = context;
- this.path = path;
+ this.pd = pd;
}
@@ -131,26 +172,15 @@
/**
* {@inheritDoc}
*/
- public Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
- String propertyName) throws OperationsException,
- PropertyNotFoundException {
- ManagedObjectPath<?, ?> tmp = path;
- ManagedObject<?> mo;
+ public Collection<T> visitAbsoluteInherited(
+ AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
try {
- mo = readEntry(context, tmp, tmp.getManagedObjectDefinition());
- } catch (AuthorizationException e) {
- throw new OperationsException(e);
- } catch (CommunicationException e) {
- throw new OperationsException(e);
+ return getInheritedProperty(d.getManagedObjectPath(), d
+ .getManagedObjectDefinition(), d.getPropertyName());
+ } catch (DefaultBehaviorException e) {
+ exception = new DefaultBehaviorException(pd, e);
}
- ManagedObjectDefinition<?, ?> mod = mo.getManagedObjectDefinition();
-
- try {
- PropertyDefinition<?> dpd = mod.getPropertyDefinition(propertyName);
- return mo.getPropertyValues(dpd);
- } catch (IllegalArgumentException e) {
- throw new PropertyNotFoundException(propertyName);
- }
+ return Collections.emptySet();
}
@@ -158,10 +188,133 @@
/**
* {@inheritDoc}
*/
- public ManagedObjectPath getManagedObjectPath() {
- return path;
+ public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ return Collections.emptySet();
}
- }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ Collection<String> stringValues = d.getDefaultValues();
+ List<T> values = new ArrayList<T>(stringValues.size());
+
+ for (String stringValue : stringValues) {
+ try {
+ values.add(pd.decodeValue(stringValue));
+ } catch (IllegalPropertyValueStringException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ break;
+ }
+ }
+
+ return values;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitRelativeInherited(
+ RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+ try {
+ return getInheritedProperty(d.getManagedObjectPath(p), d
+ .getManagedObjectDefinition(), d.getPropertyName());
+ } catch (DefaultBehaviorException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ }
+ return Collections.emptySet();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ return Collections.emptySet();
+ }
+
+
+
+ // Get an inherited property value.
+ private Collection<T> getInheritedProperty(ManagedObjectPath target,
+ AbstractManagedObjectDefinition<?, ?> d, String propertyName)
+ throws DefaultBehaviorException {
+ try {
+ // First check that the requested type of managed object
+ // corresponds to the path.
+ AbstractManagedObjectDefinition<?, ?> supr = target
+ .getManagedObjectDefinition();
+ if (!supr.isParentOf(d)) {
+ throw new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION);
+ }
+
+ // Get the actual managed object definition.
+ LdapName dn = LDAPNameBuilder.create(target, context.getLDAPProfile());
+ ManagedObjectDefinition<?, ?> mod = getEntryDefinition(context, d, dn);
+
+ PropertyDefinition<?> pd2;
+ try {
+ pd2 = mod.getPropertyDefinition(propertyName);
+ } catch (IllegalArgumentException e) {
+ throw new PropertyNotFoundException(propertyName);
+ }
+
+ String attrID = context.getLDAPProfile().getAttributeName(mod, pd2);
+ Attributes attributes = context.getLDAPConnection().readEntry(dn,
+ Collections.singleton(attrID));
+ Attribute attr = attributes.get(attrID);
+ if (attr == null || attr.size() == 0) {
+ // Recursively retrieve this property's default values.
+ Collection<?> tmp = getDefaultValues(context, target, pd2);
+ Collection<T> values = new ArrayList<T>(tmp.size());
+ for (Object o : tmp) {
+ T value;
+ try {
+ value = pd.castValue(o);
+ } catch (ClassCastException e) {
+ throw new IllegalPropertyValueException(pd, o);
+ }
+ pd.validateValue(value);
+ values.add(value);
+ }
+ return values;
+ } else {
+ Collection<T> values = new LinkedList<T>();
+ NamingEnumeration<?> ne = attr.getAll();
+ while (ne.hasMore()) {
+ Object value = ne.next();
+ if (value != null) {
+ values.add(pd.decodeValue(value.toString()));
+ }
+ }
+ return values;
+ }
+ } catch (DefinitionDecodingException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (PropertyNotFoundException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (IllegalPropertyValueException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (IllegalPropertyValueStringException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (NameNotFoundException e) {
+ throw new DefaultBehaviorException(pd,
+ new ManagedObjectNotFoundException());
+ } catch (NoPermissionException e) {
+ throw new DefaultBehaviorException(pd, new AuthorizationException(e));
+ } catch (NamingException e) {
+ throw new DefaultBehaviorException(pd, new CommunicationException(e));
+ }
+ }
+ };
@@ -176,30 +329,8 @@
*/
static ManagedObject<RootCfgClient> getRootManagedObject(
LDAPManagementContext context) {
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, ManagedObjectPath.emptyPath());
- PropertySet properties = PropertySet.create(RootCfgDefn.getInstance(),
- PropertyProvider.DEFAULT_PROVIDER, i, exceptions);
-
- // Should never get any exceptions.
- if (!exceptions.isEmpty()) {
- throw new RuntimeException(
- "Got exceptions when creating root managed object");
- }
-
return new LDAPManagedObject<RootCfgClient>(context, RootCfgDefn
- .getInstance(), ManagedObjectPath.emptyPath(), properties);
- }
-
-
-
- // Create a new child LDAP managed object.
- private static <M extends ConfigurationClient>
- ManagedObject<M> createLDAPManagedObject(
- LDAPManagementContext context, ManagedObjectDefinition<M, ?> d,
- ManagedObjectPath p, PropertySet properties) {
- return new LDAPManagedObject<M>(context, d, p, properties);
+ .getInstance(), ManagedObjectPath.emptyPath(), new PropertySet(), true);
}
@@ -247,104 +378,17 @@
return d.resolveManagedObjectDefinition(resolver);
}
-
-
- // Read the entry identified by the path and which is a sub-type of
- // the specified definition.
- private static <M extends ConfigurationClient>
- ManagedObject<? extends M> readEntry(
- final LDAPManagementContext context, ManagedObjectPath p,
- AbstractManagedObjectDefinition<M, ?> d)
- throws DefinitionDecodingException, ManagedObjectDecodingException,
- ManagedObjectNotFoundException, AuthorizationException,
- CommunicationException {
- LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
-
- final ManagedObjectDefinition<? extends M, ?> mod;
- final Attributes attributes;
- try {
- mod = getEntryDefinition(context, d, dn);
- ArrayList<String> attrIds = new ArrayList<String>();
- for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
- String attrId = context.getLDAPProfile().getAttributeName(mod, pd);
- attrIds.add(attrId);
- }
- attributes = context.getLDAPConnection().readEntry(dn, attrIds);
- } catch (NameNotFoundException e) {
- throw new ManagedObjectNotFoundException();
- } catch (NoPermissionException e) {
- throw new AuthorizationException(e);
- } catch (NamingException e) {
- throw new CommunicationException(e);
- }
-
- // Create a provider which uses LDAP string representations.
-
- // TODO: the exception handling is a bit of a hack here.
- final List<NamingException> nelist = new LinkedList<NamingException>();
- StringPropertyProvider provider = new StringPropertyProvider() {
-
- public Collection<String> getPropertyValues(PropertyDefinition<?> d)
- throws IllegalArgumentException {
- String attrID = context.getLDAPProfile().getAttributeName(mod, d);
- Attribute attribute = attributes.get(attrID);
- List<String> values = new LinkedList<String>();
-
- if (attribute != null && attribute.size() != 0) {
- try {
- NamingEnumeration<?> ldapValues = attribute.getAll();
- while (ldapValues.hasMore()) {
- Object obj = ldapValues.next();
- if (obj != null) {
- values.add(obj.toString());
- }
- }
- } catch (NamingException e) {
- nelist.add(e);
- }
- }
-
- return values;
- }
-
- };
-
- // There can only be at most one exception.
- if (!nelist.isEmpty()) {
- try {
- throw nelist.get(0);
- } catch (NameNotFoundException e) {
- throw new ManagedObjectNotFoundException();
- } catch (NoPermissionException e) {
- throw new AuthorizationException(e);
- } catch (NamingException e) {
- throw new CommunicationException(e);
- }
- }
-
- // Now decode the properties using the provider.
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, p);
- PropertySet properties = PropertySet.create(mod, provider, i, exceptions);
- ManagedObject<? extends M> mo = createLDAPManagedObject(context, mod, p,
- properties);
-
- // If there were no decoding problems then return the object,
- // otherwise throw an operations exception.
- if (exceptions.isEmpty()) {
- return mo;
- } else {
- throw new ManagedObjectDecodingException(mo, exceptions);
- }
- }
+ // The LDAP management context used for the ldap connection.
+ private final LDAPManagementContext context;
// The managed object definition associated with this managed
// object.
private final ManagedObjectDefinition<C, ?> definition;
- // The LDAP management context used for the ldap connection.
- private final LDAPManagementContext context;
+ // Indicates whether or not this managed object exists on the server
+ // (false means the managed object is new and has not been
+ // committed).
+ private boolean existsOnServer;
// The path associated with this managed object.
private final ManagedObjectPath<?, ?> path;
@@ -357,11 +401,12 @@
// Create an new LDAP managed object with the provided JNDI context.
private LDAPManagedObject(LDAPManagementContext context,
ManagedObjectDefinition<C, ?> d, ManagedObjectPath path,
- PropertySet properties) {
+ PropertySet properties, boolean existsOnServer) {
this.definition = d;
this.context = context;
this.path = path;
this.properties = properties;
+ this.existsOnServer = existsOnServer;
}
@@ -369,36 +414,30 @@
/**
* {@inheritDoc}
*/
- public void commit() throws ConcurrentModificationException,
- OperationRejectedException, AuthorizationException,
- CommunicationException {
- // Build the list of modified attributes.
- ManagedObjectDefinition<C, ?> d = getManagedObjectDefinition();
- Attributes mods = new BasicAttributes();
- for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+ public void commit() throws MissingMandatoryPropertiesException,
+ ConcurrentModificationException, OperationRejectedException,
+ AuthorizationException, CommunicationException,
+ ManagedObjectAlreadyExistsException {
+ // First make sure all mandatory properties are defined.
+ List<PropertyIsMandatoryException> exceptions =
+ new LinkedList<PropertyIsMandatoryException>();
+
+ for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
Property<?> p = properties.getProperty(pd);
- if (p.isModified()) {
- String attrID = context.getLDAPProfile().getAttributeName(d, pd);
- Attribute attribute = new BasicAttribute(attrID);
- encodeProperty(attribute, pd, properties);
- mods.put(attribute);
+ if (pd.hasOption(PropertyOption.MANDATORY) && p.isEmpty()) {
+ exceptions.add(new PropertyIsMandatoryException(pd));
}
}
- // Perform the LDAP modification if something has changed.
- if (mods.size() > 0) {
- try {
- LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
- context.getLDAPConnection().modifyEntry(dn, mods);
- } catch (NoPermissionException e) {
- throw new AuthorizationException(e);
- } catch (OperationNotSupportedException e) {
- // Unwilling to perform.
- throw new OperationRejectedException(e);
- } catch (NamingException e) {
- // Just treat it as a communication problem.
- throw new CommunicationException(e);
- }
+ if (!exceptions.isEmpty()) {
+ throw new MissingMandatoryPropertiesException(exceptions);
+ }
+
+ // Commit the managed object.
+ if (existsOnServer) {
+ commitExistingManagedObject();
+ } else {
+ commitNewManagedObject();
}
}
@@ -410,60 +449,11 @@
public <M extends ConfigurationClient, N extends M>
ManagedObject<N> createChild(
InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- String name, PropertyProvider p) throws IllegalArgumentException,
- ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
- ConcurrentModificationException, OperationRejectedException,
- AuthorizationException, CommunicationException {
+ String name, Collection<DefaultBehaviorException> exceptions)
+ throws IllegalArgumentException {
validateRelationDefinition(r);
-
ManagedObjectPath childPath = path.child(r, name);
-
- // First make sure all the properties are valid.
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, childPath);
- PropertySet properties = PropertySet.create(d, p, i, exceptions);
- if (!exceptions.isEmpty()) {
- ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath,
- properties);
- throw new ManagedObjectDecodingException(mo, exceptions);
- }
-
- ensureThisManagedObjectExists();
-
- // TODO: this implementation does not handle relations which
- // comprise of more than one RDN arc (this will probably never
- // be required anyway).
- LdapName dn = LDAPNameBuilder.create(path, r, context.getLDAPProfile());
- if (!entryExists(dn)) {
- // Need to create the child managed object's parent entry i.e.
- // the entry representing the relation itself.
- Attributes attributes = new BasicAttributes();
-
- // Create the branch's object class attribute.
- Attribute oc = new BasicAttribute("objectClass");
- for (String objectClass : context.getLDAPProfile()
- .getInstantiableRelationObjectClasses(r)) {
- oc.add(objectClass);
- }
- attributes.put(oc);
-
- // Create the branch's naming attribute.
- Rdn rdn = dn.getRdn(dn.size() - 1);
- attributes.put(rdn.getType(), rdn.getValue().toString());
-
- // Create the entry.
- try {
- context.getLDAPConnection().createEntry(dn, attributes);
- } catch (OperationNotSupportedException e) {
- // Unwilling to perform.
- throw new OperationRejectedException(e);
- } catch (NamingException e) {
- adaptNamingException(e);
- }
- }
-
- return createManagedObject(childPath, d, properties);
+ return createNewManagedObject(d, childPath, exceptions);
}
@@ -474,28 +464,11 @@
public <M extends ConfigurationClient, N extends M>
ManagedObject<N> createChild(
OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- PropertyProvider p) throws IllegalArgumentException,
- ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
- ConcurrentModificationException, OperationRejectedException,
- AuthorizationException, CommunicationException {
+ Collection<DefaultBehaviorException> exceptions)
+ throws IllegalArgumentException {
validateRelationDefinition(r);
-
ManagedObjectPath childPath = path.child(r);
-
- // First make sure all the properties are valid.
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, childPath);
- PropertySet properties = PropertySet.create(d, p, i, exceptions);
- if (!exceptions.isEmpty()) {
- ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath,
- properties);
- throw new ManagedObjectDecodingException(mo, exceptions);
- }
-
- ensureThisManagedObjectExists();
-
- return createManagedObject(childPath, d, properties);
+ return createNewManagedObject(d, childPath, exceptions);
}
@@ -511,7 +484,7 @@
CommunicationException {
validateRelationDefinition(d);
ensureThisManagedObjectExists();
- return readEntry(context, path.child(d, name), d.getChildDefinition());
+ return readManagedObject(d.getChildDefinition(), path.child(d, name));
}
@@ -526,7 +499,7 @@
AuthorizationException, CommunicationException {
validateRelationDefinition(d);
ensureThisManagedObjectExists();
- return readEntry(context, path.child(d), d.getChildDefinition());
+ return readManagedObject(d.getChildDefinition(), path.child(d));
}
@@ -541,7 +514,7 @@
AuthorizationException, CommunicationException {
validateRelationDefinition(d);
ensureThisManagedObjectExists();
- return readEntry(context, path.child(d), d.getChildDefinition());
+ return readManagedObject(d.getChildDefinition(), path.child(d));
}
@@ -674,6 +647,14 @@
public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
throws IllegalPropertyValueException, PropertyIsReadOnlyException,
PropertyIsMandatoryException, IllegalArgumentException {
+ if (d.hasOption(PropertyOption.MONITORING)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
+ if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
properties.setPropertyValue(d, value);
}
@@ -686,6 +667,14 @@
Collection<T> values) throws IllegalPropertyValueException,
PropertyIsSingleValuedException, PropertyIsReadOnlyException,
PropertyIsMandatoryException, IllegalArgumentException {
+ if (d.hasOption(PropertyOption.MONITORING)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
+ if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
properties.setPropertyValues(d, values);
}
@@ -711,30 +700,118 @@
- // Creates a new managed object. The parent LDAP entry is assumed to
- // already exist.
- private <N extends ConfigurationClient> ManagedObject<N> createManagedObject(
- ManagedObjectPath path, ManagedObjectDefinition<N, ?> d,
- PropertySet properties) throws ManagedObjectAlreadyExistsException,
- OperationRejectedException, AuthorizationException,
- CommunicationException {
+ // Commit modifications made to this managed object.
+ private void commitExistingManagedObject()
+ throws ConcurrentModificationException, OperationRejectedException,
+ AuthorizationException, CommunicationException {
+ // Build the list of modified attributes.
+ Attributes mods = new BasicAttributes();
+ for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+ Property<?> p = properties.getProperty(pd);
+ if (p.isModified()) {
+ String attrID = context.getLDAPProfile().getAttributeName(definition,
+ pd);
+ Attribute attribute = new BasicAttribute(attrID);
+ encodeProperty(attribute, pd, properties);
+ mods.put(attribute);
+ }
+ }
+
+ // Perform the LDAP modification if something has changed.
+ if (mods.size() > 0) {
+ try {
+ LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
+ context.getLDAPConnection().modifyEntry(dn, mods);
+ } catch (NoPermissionException e) {
+ throw new AuthorizationException(e);
+ } catch (OperationNotSupportedException e) {
+ // Unwilling to perform.
+ throw new OperationRejectedException(e);
+ } catch (NamingException e) {
+ // Just treat it as a communication problem.
+ throw new CommunicationException(e);
+ }
+ }
+
+ // The changes were committed successfully so update this managed
+ // object's state.
+ properties.commit();
+ }
+
+
+
+ // Commit this new managed object.
+ private void commitNewManagedObject() throws AuthorizationException,
+ CommunicationException, OperationRejectedException,
+ ConcurrentModificationException, ManagedObjectAlreadyExistsException {
+ // First make sure that the parent managed object still exists.
+ ManagedObjectPath<?, ?> parent = path.parent();
+ if (!parent.isEmpty()) {
+ LdapName dn = LDAPNameBuilder.create(parent, context.getLDAPProfile());
+ if (!entryExists(dn)) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ // We may need to create the parent "relation" entry if this is a
+ // child of an instantiable relation.
+ RelationDefinition<?, ?> r = path.getRelationDefinition();
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<?, ?> ir =
+ (InstantiableRelationDefinition<?, ?>) r;
+
+ // TODO: this implementation does not handle relations which
+ // comprise of more than one RDN arc (this will probably never
+ // be required anyway).
+ LdapName dn = LDAPNameBuilder
+ .create(parent, ir, context.getLDAPProfile());
+ if (!entryExists(dn)) {
+ // We need to create the entry.
+ Attributes attributes = new BasicAttributes();
+
+ // Create the branch's object class attribute.
+ Attribute oc = new BasicAttribute("objectClass");
+ for (String objectClass : context.getLDAPProfile()
+ .getInstantiableRelationObjectClasses(ir)) {
+ oc.add(objectClass);
+ }
+ attributes.put(oc);
+
+ // Create the branch's naming attribute.
+ Rdn rdn = dn.getRdn(dn.size() - 1);
+ attributes.put(rdn.getType(), rdn.getValue().toString());
+
+ // Create the entry.
+ try {
+ context.getLDAPConnection().createEntry(dn, attributes);
+ } catch (OperationNotSupportedException e) {
+ // Unwilling to perform.
+ throw new OperationRejectedException(e);
+ } catch (NamingException e) {
+ adaptNamingException(e);
+ }
+ }
+ }
+
+ // Now add the entry representing this new managed object.
LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
Attributes attributes = new BasicAttributes(true);
- // Create the child's object class attribute.
+ // Create the object class attribute.
Attribute oc = new BasicAttribute("objectclass");
- for (String objectClass : context.getLDAPProfile().getObjectClasses(d)) {
+ for (String objectClass : context.getLDAPProfile().getObjectClasses(
+ definition)) {
oc.add(objectClass);
}
attributes.put(oc);
- // Create the child's naming attribute.
+ // Create the naming attribute.
Rdn rdn = dn.getRdn(dn.size() - 1);
attributes.put(rdn.getType(), rdn.getValue().toString());
// Create the remaining attributes.
- for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
- String attrID = context.getLDAPProfile().getAttributeName(d, pd);
+ for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+ String attrID = context.getLDAPProfile().getAttributeName(definition, pd);
Attribute attribute = new BasicAttribute(attrID);
encodeProperty(attribute, pd, properties);
if (attribute.size() != 0) {
@@ -754,7 +831,108 @@
adaptNamingException(e);
}
- return new LDAPManagedObject<N>(context, d, path, properties);
+ // The entry was created successfully so update this managed
+ // object's state.
+ properties.commit();
+ existsOnServer = true;
+ }
+
+
+
+ // Create a managed object which already exists on the server.
+ private <M extends ConfigurationClient>
+ ManagedObject<M> createExistingManagedObject(
+ ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+ PropertySet properties) {
+ return new LDAPManagedObject<M>(context, d, p, properties, true);
+ }
+
+
+
+ // Creates a new managed object with no active values, just default
+ // values.
+ private <M extends ConfigurationClient>
+ ManagedObject<M> createNewManagedObject(
+ ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+ Collection<DefaultBehaviorException> exceptions) {
+ PropertySet childProperties = new PropertySet();
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+ try {
+ createProperty(childProperties, p, pd);
+ } catch (DefaultBehaviorException e) {
+ // Add the exception if requested.
+ if (exceptions != null) {
+ exceptions.add(e);
+ }
+ }
+ }
+
+ return new LDAPManagedObject<M>(context, d, p, childProperties, false);
+ }
+
+
+
+ // Create an empty property.
+ private <T> void createProperty(PropertySet properties, ManagedObjectPath p,
+ PropertyDefinition<T> pd) throws DefaultBehaviorException {
+ try {
+ Collection<T> defaultValues = DefaultValueFinder.getDefaultValues(
+ context, p, pd);
+ properties.addProperty(pd, defaultValues, Collections.<T> emptySet());
+ } catch (DefaultBehaviorException e) {
+ // Make sure that we have still created the property.
+ properties.addProperty(pd, Collections.<T> emptySet(), Collections
+ .<T> emptySet());
+ throw e;
+ }
+ }
+
+
+
+ // Create a property using the provided string values.
+ private <T> void decodeProperty(PropertySet newProperties,
+ ManagedObjectPath p, PropertyDefinition<T> pd, List<String> values)
+ throws PropertyException {
+ PropertyException exception = null;
+
+ // Get the property's active values.
+ Collection<T> activeValues = new ArrayList<T>(values.size());
+ for (String value : values) {
+ try {
+ activeValues.add(pd.decodeValue(value));
+ } catch (IllegalPropertyValueStringException e) {
+ exception = e;
+ }
+ }
+
+ if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ // This exception takes precedence over previous exceptions.
+ exception = new PropertyIsSingleValuedException(pd);
+ T value = activeValues.iterator().next();
+ activeValues.clear();
+ activeValues.add(value);
+ }
+
+ if (activeValues.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+ // The active values maybe empty because of a previous exception.
+ if (exception == null) {
+ exception = new PropertyIsMandatoryException(pd);
+ }
+ }
+
+ // Get the property's default values.
+ Collection<T> defaultValues;
+ try {
+ defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd);
+ } catch (DefaultBehaviorException e) {
+ defaultValues = Collections.emptySet();
+ exception = e;
+ }
+
+ newProperties.addProperty(pd, defaultValues, activeValues);
+ if (exception != null) {
+ throw exception;
+ }
}
@@ -775,9 +953,11 @@
private void ensureThisManagedObjectExists()
throws ConcurrentModificationException, CommunicationException,
AuthorizationException {
- LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
- if (!entryExists(dn)) {
- throw new ConcurrentModificationException();
+ if (!path.isEmpty()) {
+ LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
+ if (!entryExists(dn)) {
+ throw new ConcurrentModificationException();
+ }
}
}
@@ -796,6 +976,75 @@
+ // Read the entry identified by the path and which is a sub-type of
+ // the specified definition.
+ private <M extends ConfigurationClient>
+ ManagedObject<? extends M> readManagedObject(
+ AbstractManagedObjectDefinition<M, ?> d, ManagedObjectPath p)
+ throws DefinitionDecodingException, ManagedObjectDecodingException,
+ ManagedObjectNotFoundException, AuthorizationException,
+ CommunicationException {
+ try {
+ // Read the entry associated with the managed object.
+ LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
+ ManagedObjectDefinition<? extends M, ?> mod = getEntryDefinition(context,
+ d, dn);
+
+ ArrayList<String> attrIds = new ArrayList<String>();
+ for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+ String attrId = context.getLDAPProfile().getAttributeName(mod, pd);
+ attrIds.add(attrId);
+ }
+
+ Attributes attributes = context.getLDAPConnection()
+ .readEntry(dn, attrIds);
+
+ // Build the managed object's properties.
+ List<PropertyException> exceptions = new LinkedList<PropertyException>();
+ PropertySet newProperties = new PropertySet();
+ for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+ String attrID = context.getLDAPProfile().getAttributeName(mod, pd);
+ Attribute attribute = attributes.get(attrID);
+ List<String> values = new LinkedList<String>();
+
+ if (attribute != null && attribute.size() != 0) {
+ NamingEnumeration<?> ldapValues = attribute.getAll();
+ while (ldapValues.hasMore()) {
+ Object obj = ldapValues.next();
+ if (obj != null) {
+ values.add(obj.toString());
+ }
+ }
+ }
+
+ try {
+ decodeProperty(newProperties, p, pd, values);
+ } catch (PropertyException e) {
+ exceptions.add(e);
+ }
+ }
+
+ // If there were no decoding problems then return the object,
+ // otherwise throw an operations exception.
+ ManagedObject<? extends M> mo = createExistingManagedObject(mod, p,
+ newProperties);
+
+ if (exceptions.isEmpty()) {
+ return mo;
+ } else {
+ throw new ManagedObjectDecodingException(mo, exceptions);
+ }
+ } catch (NameNotFoundException e) {
+ throw new ManagedObjectNotFoundException();
+ } catch (NoPermissionException e) {
+ throw new AuthorizationException(e);
+ } catch (NamingException e) {
+ throw new CommunicationException(e);
+ }
+ }
+
+
+
// Remove the named managed object.
private void removeManagedObject(ManagedObjectPath p)
throws CommunicationException, AuthorizationException,
--
Gitblit v1.10.0