From 02805157fa504b3dbf701a62280ca9aaf82183b5 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Wed, 05 Sep 2007 20:12:11 +0000
Subject: [PATCH] Partial fix for issue 1449: administration framework aggregation support
---
opends/src/server/org/opends/server/admin/server/ServerManagementContext.java | 174 ++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 139 insertions(+), 35 deletions(-)
diff --git a/opends/src/server/org/opends/server/admin/server/ServerManagementContext.java b/opends/src/server/org/opends/server/admin/server/ServerManagementContext.java
index ea2f943..a8d3391 100644
--- a/opends/src/server/org/opends/server/admin/server/ServerManagementContext.java
+++ b/opends/src/server/org/opends/server/admin/server/ServerManagementContext.java
@@ -47,6 +47,7 @@
import org.opends.messages.Message;
import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AggregationPropertyDefinition;
import org.opends.server.admin.AliasDefaultBehaviorProvider;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ConfigurationClient;
@@ -62,14 +63,17 @@
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.ManagedObjectPath;
import org.opends.server.admin.PropertyDefinition;
+import org.opends.server.admin.PropertyDefinitionVisitor;
import org.opends.server.admin.PropertyException;
import org.opends.server.admin.PropertyIsMandatoryException;
import org.opends.server.admin.PropertyIsSingleValuedException;
import org.opends.server.admin.PropertyNotFoundException;
import org.opends.server.admin.PropertyOption;
+import org.opends.server.admin.Reference;
import org.opends.server.admin.RelationDefinition;
import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
+import org.opends.server.admin.UnknownPropertyDefinitionException;
import org.opends.server.admin.DefinitionDecodingException.Reason;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.admin.std.server.RootCfg;
@@ -263,22 +267,22 @@
throw new PropertyNotFoundException(propertyName);
}
- List<String> stringValues = getAttribute(mod, pd2, configEntry);
- if (stringValues.isEmpty()) {
+ List<AttributeValue> values = getAttribute(mod, pd2, configEntry);
+ if (values.isEmpty()) {
// Recursively retrieve this property's default values.
Collection<T> tmp = find(target, pd2);
- Collection<T> values = new ArrayList<T>(tmp.size());
+ Collection<T> pvalues = new ArrayList<T>(tmp.size());
for (T value : tmp) {
pd1.validateValue(value);
- values.add(value);
+ pvalues.add(value);
}
- return values;
+ return pvalues;
} else {
- Collection<T> values = new ArrayList<T>(stringValues.size());
- for (String s : stringValues) {
- values.add(pd1.decodeValue(s));
+ Collection<T> pvalues = new ArrayList<T>(values.size());
+ for (AttributeValue value : values) {
+ pvalues.add(ValueDecoder.decode(pd1, value));
}
- return values;
+ return pvalues;
}
} catch (DefinitionDecodingException e) {
throw new DefaultBehaviorException(pd1, e);
@@ -321,7 +325,76 @@
String oc = LDAPProfile.getInstance().getObjectClass(d);
return entry.hasObjectClass(oc);
}
- };
+ }
+
+
+
+ /**
+ * A visitor which is used to decode property LDAP values.
+ */
+ private static final class ValueDecoder extends
+ PropertyDefinitionVisitor<Object, String> {
+
+ /**
+ * Decodes the provided property LDAP value.
+ *
+ * @param <PD>
+ * The type of the property.
+ * @param pd
+ * The property definition.
+ * @param value
+ * The LDAP string representation.
+ * @return Returns the decoded LDAP value.
+ * @throws IllegalPropertyValueStringException
+ * If the property value could not be decoded because it
+ * was invalid.
+ */
+ public static <PD> PD decode(PropertyDefinition<PD> pd,
+ AttributeValue value) throws IllegalPropertyValueStringException {
+ String s = value.getStringValue();
+ return pd.castValue(pd.accept(new ValueDecoder(), s));
+ }
+
+
+
+ // Prevent instantiation.
+ private ValueDecoder() {
+ // No implementation required.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <C extends ConfigurationClient, S extends Configuration>
+ Object visitAggregation(AggregationPropertyDefinition<C, S> d, String p) {
+ // Aggregations values are stored as full DNs in LDAP, but
+ // just their common name is exposed in the admin framework.
+ try {
+ Reference<C, S> reference = Reference.parseDN(d.getParentPath(), d
+ .getRelationDefinition(), p);
+ return reference.getName();
+ } catch (IllegalArgumentException e) {
+ throw new IllegalPropertyValueStringException(d, p);
+ }
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <T> Object visitUnknown(PropertyDefinition<T> d, String p)
+ throws UnknownPropertyDefinitionException {
+ // By default the property definition's decoder will do.
+ return d.decodeValue(p);
+ }
+ }
+
+
// Singleton instance.
private final static ServerManagementContext INSTANCE =
@@ -399,6 +472,12 @@
* Gets the effective value of a property in the named managed
* object.
*
+ * @param <C>
+ * The type of client managed object configuration that the
+ * path definition refers to.
+ * @param <S>
+ * The type of server managed object configuration that the
+ * path definition refers to.
* @param <PD>
* The type of the property to be retrieved.
* @param path
@@ -417,7 +496,8 @@
* If the named managed object could not be found or if it
* could not be decoded.
*/
- public <PD> PD getPropertyValue(ManagedObjectPath<?, ?> path,
+ public <C extends ConfigurationClient, S extends Configuration, PD>
+ PD getPropertyValue(ManagedObjectPath<C, S> path,
PropertyDefinition<PD> pd) throws IllegalArgumentException,
ConfigException, PropertyException {
SortedSet<PD> values = getPropertyValues(path, pd);
@@ -434,6 +514,12 @@
* Gets the effective values of a property in the named managed
* object.
*
+ * @param <C>
+ * The type of client managed object configuration that the
+ * path definition refers to.
+ * @param <S>
+ * The type of server managed object configuration that the
+ * path definition refers to.
* @param <PD>
* The type of the property to be retrieved.
* @param path
@@ -452,15 +538,27 @@
* If the named managed object could not be found or if it
* could not be decoded.
*/
- public <PD> SortedSet<PD> getPropertyValues(ManagedObjectPath<?, ?> path,
+ @SuppressWarnings("unchecked")
+ public <C extends ConfigurationClient, S extends Configuration, PD>
+ SortedSet<PD> getPropertyValues(ManagedObjectPath<C, S> path,
PropertyDefinition<PD> pd) throws IllegalArgumentException,
ConfigException, PropertyException {
+ // Check that the requested property is from the definition
+ // associated with the path.
+ AbstractManagedObjectDefinition<C, S> d = path.getManagedObjectDefinition();
+ PropertyDefinition<?> tmp = d.getPropertyDefinition(pd.getName());
+ if (tmp != pd) {
+ throw new IllegalArgumentException("The property " + pd.getName()
+ + " is not associated with a " + d.getName());
+ }
+
+ // Determine the exact type of managed object referenced by the
+ // path.
DN dn = DNBuilder.create(path);
ConfigEntry configEntry = getManagedObjectConfigEntry(dn);
DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
- AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition();
- ManagedObjectDefinition<?, ?> mod;
+ ManagedObjectDefinition<? extends C, ? extends S> mod;
try {
mod = d.resolveManagedObjectDefinition(resolver);
@@ -469,8 +567,13 @@
.createDecodingExceptionAdaptor(dn, e);
}
- List<String> values = getAttribute(mod, pd, configEntry);
- return decodeProperty(path, pd, values, null);
+ // Make sure we use the correct property definition, the
+ // provided one might have been overridden in the resolved
+ // definition.
+ pd = (PropertyDefinition<PD>) mod.getPropertyDefinition(pd.getName());
+
+ List<AttributeValue> values = getAttribute(mod, pd, configEntry);
+ return decodeProperty(path.asSubType(mod), pd, values, null);
}
@@ -649,7 +752,7 @@
Map<PropertyDefinition<?>, SortedSet<?>> properties =
new HashMap<PropertyDefinition<?>, SortedSet<?>>();
for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
- List<String> values = getAttribute(mod, pd, configEntry);
+ List<AttributeValue> values = getAttribute(mod, pd, configEntry);
try {
SortedSet<?> pvalues = decodeProperty(path, pd, values, newConfigEntry);
properties.put(pd, pvalues);
@@ -686,16 +789,16 @@
// Create a property using the provided string values.
private <T> SortedSet<T> decodeProperty(ManagedObjectPath<?, ?> path,
- PropertyDefinition<T> pd, List<String> stringValues,
+ PropertyDefinition<T> pd, List<AttributeValue> values,
ConfigEntry newConfigEntry) throws PropertyException {
PropertyException exception = null;
- SortedSet<T> values = new TreeSet<T>(pd);
+ SortedSet<T> pvalues = new TreeSet<T>(pd);
- if (!stringValues.isEmpty()) {
+ if (!values.isEmpty()) {
// The property has values defined for it.
- for (String value : stringValues) {
+ for (AttributeValue value : values) {
try {
- values.add(pd.decodeValue(value));
+ pvalues.add(ValueDecoder.decode(pd, value));
} catch (IllegalPropertyValueStringException e) {
exception = e;
}
@@ -703,21 +806,21 @@
} else {
// No values defined so get the defaults.
try {
- values.addAll(getDefaultValues(path, pd, newConfigEntry));
+ pvalues.addAll(getDefaultValues(path, pd, newConfigEntry));
} catch (DefaultBehaviorException e) {
exception = e;
}
}
- if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ if (pvalues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
// This exception takes precedence over previous exceptions.
exception = new PropertyIsSingleValuedException(pd);
- T value = values.first();
- values.clear();
- values.add(value);
+ T value = pvalues.first();
+ pvalues.clear();
+ pvalues.add(value);
}
- if (values.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+ if (pvalues.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
// The values maybe empty because of a previous exception.
if (exception == null) {
exception = new PropertyIsMandatoryException(pd);
@@ -727,29 +830,30 @@
if (exception != null) {
throw exception;
} else {
- return values;
+ return pvalues;
}
}
// Gets the attribute associated with a property from a ConfigEntry.
- private List<String> getAttribute(ManagedObjectDefinition<?, ?> d,
+ private List<AttributeValue> getAttribute(ManagedObjectDefinition<?, ?> d,
PropertyDefinition<?> pd, ConfigEntry configEntry) {
// TODO: we create a default attribute type if it is
// undefined. We should log a warning here if this is the case
// since the attribute should have been defined.
String attrID = LDAPProfile.getInstance().getAttributeName(d, pd);
AttributeType type = DirectoryServer.getAttributeType(attrID, true);
- AttributeValueDecoder<String> decoder =
- new AttributeValueDecoder<String>() {
+ AttributeValueDecoder<AttributeValue> decoder =
+ new AttributeValueDecoder<AttributeValue>() {
- public String decode(AttributeValue value) throws DirectoryException {
- return value.getStringValue();
+ public AttributeValue decode(AttributeValue value)
+ throws DirectoryException {
+ return value;
}
};
- List<String> values = new LinkedList<String>();
+ List<AttributeValue> values = new LinkedList<AttributeValue>();
try {
configEntry.getEntry().getAttributeValues(type, decoder, values);
} catch (DirectoryException e) {
--
Gitblit v1.10.0