opendj-sdk/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -29,9 +29,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; @@ -90,52 +92,15 @@ AbstractManagedObjectDefinition<? super C, ? super S> parent) { this.name = name; this.parent = parent; this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>(); this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>(); this.children = new HashMap<String, AbstractManagedObjectDefinition<? extends C, ? extends S>>(); // If we have a parent definition then inherit its features. if (parent != null) { this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>( parent.propertyDefinitions); this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>( parent.relationDefinitions); parent.children.put(name, this); } else { this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>(); this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>(); } this.children = new HashMap<String, AbstractManagedObjectDefinition<? extends C, ? extends S>>(); } /** * Get the named child managed object definition which inherits from this * managed object definition. * * @param name * The name of the managed object definition sub-type. * @return Returns the named child managed object definition which inherits * from this managed object definition. * @throws IllegalArgumentException * If the specified managed object definition name was null or empty * or if the requested subordinate managed object definition was not * found. */ public final AbstractManagedObjectDefinition<? extends C, ? extends S> getChild(String name) throws IllegalArgumentException { if ((name == null) || (name.length() == 0)) { throw new IllegalArgumentException("null or empty managed object name"); } AbstractManagedObjectDefinition<? extends C, ? extends S> d = children .get(name); if (d == null) { throw new IllegalArgumentException("managed object definition \"" + name + "\" not found"); } return d; } @@ -149,6 +114,121 @@ * this managed object definition. */ public final Collection<AbstractManagedObjectDefinition <? extends C, ? extends S>> getAllChildren() { List<AbstractManagedObjectDefinition<? extends C, ? extends S>> list = new ArrayList<AbstractManagedObjectDefinition<? extends C, ? extends S>>( children.values()); for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : children.values()) { list.addAll(child.getAllChildren()); } return Collections.unmodifiableCollection(list); } /** * Get all the property definitions associated with this type of * managed object. The returned collection will contain inherited * property definitions. * * @return Returns an unmodifiable collection containing all the * property definitions associated with this type of managed * object. */ public final Collection<PropertyDefinition<?>> getAllPropertyDefinitions() { if (parent == null) { return getPropertyDefinitions(); } else { List<PropertyDefinition<?>> list = new ArrayList<PropertyDefinition<?>>( propertyDefinitions.values()); list.addAll(parent.getAllPropertyDefinitions()); return Collections.unmodifiableCollection(list); } } /** * Get all the relation definitions associated with this type of * managed object. The returned collection will contain inherited * relation definitions. * * @return Returns an unmodifiable collection containing all the * relation definitions associated with this type of managed * object. */ public final Collection<RelationDefinition<?, ?>> getAllRelationDefinitions() { if (parent == null) { return getRelationDefinitions(); } else { List<RelationDefinition<?, ?>> list = new ArrayList<RelationDefinition<?, ?>>(relationDefinitions.values()); list.addAll(parent.getAllRelationDefinitions()); return Collections.unmodifiableCollection(list); } } /** * Get the named child managed object definition which inherits from * this managed object definition. This method will recursively * search down through the inheritance hierarchy. * * @param name * The name of the managed object definition sub-type. * @return Returns the named child managed object definition which * inherits from this managed object definition. * @throws IllegalArgumentException * If the specified managed object definition name was * null or empty or if the requested subordinate managed * object definition was not found. */ public final AbstractManagedObjectDefinition<? extends C, ? extends S> getChild(String name) throws IllegalArgumentException { if ((name == null) || (name.length() == 0)) { throw new IllegalArgumentException("null or empty managed object name"); } AbstractManagedObjectDefinition<? extends C, ? extends S> d = children .get(name); if (d == null) { // Recursively search. for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : children.values()) { try { d = child.getChild(name); break; } catch (IllegalArgumentException e) { // Try the next child. } } } if (d == null) { throw new IllegalArgumentException("child managed object definition \"" + name + "\" not found"); } return d; } /** * Get the child managed object definitions which inherit directly * from this managed object definition. * * @return Returns an unmodifiable collection containing the * subordinate managed object definitions which inherit * directly from this managed object definition. */ public final Collection<AbstractManagedObjectDefinition <? extends C, ? extends S>> getChildren() { return Collections.unmodifiableCollection(children.values()); } @@ -216,16 +296,17 @@ /** * Get the specified property definition associated with this type of managed * object. * Get the specified property definition associated with this type * of managed object. The search will include any inherited property * definitions. * * @param name * The name of the property definition to be retrieved. * @return Returns the specified property definition associated with this type * of managed object. * @return Returns the specified property definition associated with * this type of managed object. * @throws IllegalArgumentException * If the specified property name was null or empty or if the * requested property definition was not found. * If the specified property name was null or empty or if * the requested property definition was not found. */ public final PropertyDefinition getPropertyDefinition(String name) throws IllegalArgumentException { @@ -234,9 +315,14 @@ } PropertyDefinition d = propertyDefinitions.get(name); if (d == null) { throw new IllegalArgumentException("property definition \"" + name + "\" not found"); if (parent != null) { return parent.getPropertyDefinition(name); } else { throw new IllegalArgumentException("property definition \"" + name + "\" not found"); } } return d; @@ -245,12 +331,13 @@ /** * Get all the property definitions associated with this type of * managed object. * Get the property definitions defined by this managed object * definition. The returned collection will not contain inherited * property definitions. * * @return Returns an unmodifiable collection containing all the * property definitions associated with this type of managed * object. * @return Returns an unmodifiable collection containing the * property definitions defined by this managed object * definition. */ public final Collection<PropertyDefinition<?>> getPropertyDefinitions() { return Collections.unmodifiableCollection(propertyDefinitions @@ -260,16 +347,17 @@ /** * Get the specified relation definition associated with this type of managed * object. * Get the specified relation definition associated with this type * of managed object.The search will include any inherited relation * definitions. * * @param name * The name of the relation definition to be retrieved. * @return Returns the specified relation definition associated with this type * of managed object. * @return Returns the specified relation definition associated with * this type of managed object. * @throws IllegalArgumentException * If the specified relation name was null or empty or if the * requested relation definition was not found. * If the specified relation name was null or empty or if * the requested relation definition was not found. */ public final RelationDefinition getRelationDefinition(String name) throws IllegalArgumentException { @@ -278,9 +366,14 @@ } RelationDefinition d = relationDefinitions.get(name); if (d == null) { throw new IllegalArgumentException("relation definition \"" + name + "\" not found"); if (parent != null) { return parent.getRelationDefinition(name); } else { throw new IllegalArgumentException("relation definition \"" + name + "\" not found"); } } return d; @@ -289,16 +382,16 @@ /** * Get all the relation definitions associated with this type of * managed object. * Get the relation definitions defined by this managed object * definition. The returned collection will not contain inherited * relation definitions. * * @return Returns an unmodifiable collection containing all the * relation definitions associated with this type of managed * object. * @return Returns an unmodifiable collection containing the * relation definitions defined by this managed object * definition. */ public final Collection<RelationDefinition<?,?>> getRelationDefinitions() { return Collections.unmodifiableCollection(relationDefinitions .values()); return Collections.unmodifiableCollection(relationDefinitions.values()); } opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
@@ -32,38 +32,62 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.opends.server.admin.std.client.RootCfgClient; import org.opends.server.admin.std.meta.RootCfgDefn; import org.opends.server.admin.std.server.RootCfg; /** * A path which can be used to determine the location of a managed * object instance. * * @param <C> * The type of client managed object configuration that this * path references. * @param <S> * The type of server managed object configuration that this * path references. */ public final class ManagedObjectPath { public final class ManagedObjectPath <C extends ConfigurationClient, S extends Configuration> { /** * Abstract path element. */ private static abstract class Element { private static abstract class Element <C extends ConfigurationClient, S extends Configuration> { // The type of managed object referenced by this element. private final AbstractManagedObjectDefinition<C, S> definition; /** * Protected constructor. * * @param definition * The type of managed object referenced by this element. */ protected Element() { // No implementation required. protected Element(AbstractManagedObjectDefinition<C, S> definition) { this.definition = definition; } /** * Get the relation definition associated with this element. * Get the managed object definition associated with this element. * * @return Returns the relation definition associated with this * element. * @return Returns the managed object definition associated with * this element. */ public abstract RelationDefinition<?, ?> getRelation(); public final AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() { return definition; } @@ -74,8 +98,7 @@ * @param serializer * The managed object path serialization strategy. */ public abstract void serialize( ManagedObjectPathSerializer serializer); public abstract void serialize(ManagedObjectPathSerializer serializer); } @@ -83,19 +106,32 @@ /** * A path element representing an instantiable managed object. */ private static final class InstantiableElement extends Element { private static final class InstantiableElement <C extends ConfigurationClient, S extends Configuration> extends Element<C, S> { // The instantiable relation. private final InstantiableRelationDefinition<?, ?> r; // Factory method. private static final <C extends ConfigurationClient, S extends Configuration> InstantiableElement<C, S> create( InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d, String name) { return new InstantiableElement<C, S>(r, d, name); } // The name of the managed object. private final String name; // The instantiable relation. private final InstantiableRelationDefinition<? super C, ? super S> r; // Private constructor. private InstantiableElement( InstantiableRelationDefinition<?, ?> r, String name) { InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d, String name) { super(d); this.r = r; this.name = name; } @@ -106,20 +142,10 @@ * {@inheritDoc} */ @Override public RelationDefinition<?, ?> getRelation() { return r; } /** * {@inheritDoc} */ @Override public void serialize(ManagedObjectPathSerializer serializer) { serializer.appendManagedObjectPathElement(r, name); serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition(), name); } } @@ -127,15 +153,28 @@ /** * A path element representing an optional managed object. */ private static final class OptionalElement extends Element { private static final class OptionalElement <C extends ConfigurationClient, S extends Configuration> extends Element<C, S> { // Factory method. private static final <C extends ConfigurationClient, S extends Configuration> OptionalElement<C, S> create( OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { return new OptionalElement<C, S>(r, d); } // The optional relation. private final OptionalRelationDefinition<?, ?> r; private final OptionalRelationDefinition<? super C, ? super S> r; // Private constructor. private OptionalElement(OptionalRelationDefinition<?, ?> r) { private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { super(d); this.r = r; } @@ -145,18 +184,9 @@ * {@inheritDoc} */ @Override public RelationDefinition<?, ?> getRelation() { return r; } /** * {@inheritDoc} */ @Override public void serialize(ManagedObjectPathSerializer serializer) { serializer.appendManagedObjectPathElement(r); serializer .appendManagedObjectPathElement(r, getManagedObjectDefinition()); } } @@ -165,15 +195,29 @@ /** * A path element representing a singleton managed object. */ private static final class SingletonElement extends Element { private static final class SingletonElement <C extends ConfigurationClient, S extends Configuration> extends Element<C, S> { // Factory method. private static final <C extends ConfigurationClient, S extends Configuration> SingletonElement<C, S> create( SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { return new SingletonElement<C, S>(r, d); } // The singleton relation. private final SingletonRelationDefinition<?, ?> r; private final SingletonRelationDefinition<? super C, ? super S> r; // Private constructor. private SingletonElement(SingletonRelationDefinition<?, ?> r) { private SingletonElement( SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { super(d); this.r = r; } @@ -183,8 +227,29 @@ * {@inheritDoc} */ @Override public RelationDefinition<?, ?> getRelation() { return r; public void serialize(ManagedObjectPathSerializer serializer) { serializer .appendManagedObjectPathElement(r, getManagedObjectDefinition()); } } /** * A serialize which is used to generate the toString * representation. */ private static final class StringSerializer implements ManagedObjectPathSerializer { // Serialize to this string builder. private final StringBuilder builder; // Private constructor. private StringSerializer(StringBuilder builder) { this.builder = builder; } @@ -192,15 +257,69 @@ /** * {@inheritDoc} */ @Override public void serialize(ManagedObjectPathSerializer serializer) { serializer.appendManagedObjectPathElement(r); public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement( InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d, String name) { serializeElement(r, d); // Be careful to escape any forward slashes in the name. builder.append("+name="); builder.append(name.replace("/", "//")); } /** * {@inheritDoc} */ public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement( OptionalRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) { serializeElement(r, d); } /** * {@inheritDoc} */ public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement( SingletonRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) { serializeElement(r, d); } // Common element serialization. private <M, N> void serializeElement(RelationDefinition r, AbstractManagedObjectDefinition d) { // Always specify the relation name. builder.append("/relation="); builder.append(r.getName()); // Only specify the type if it is a sub-type of the relation's // type. if (r.getChildDefinition() != d) { builder.append("+type="); builder.append(d.getName()); } } } // Single instance of a root path. private static final ManagedObjectPath EMPTY_PATH = new ManagedObjectPath( new LinkedList<Element>()); private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH = new ManagedObjectPath<RootCfgClient, RootCfg>( new LinkedList<Element<?, ?>>(), RootCfgDefn.getInstance()); // A regular expression used to parse path elements. private static final Pattern PE_REGEXP = Pattern .compile("^\\s*relation=\\s*([^+]+)\\s*" + "(\\+\\s*type=\\s*([^+]+)\\s*)?" + "(\\+\\s*name=\\s*([^+]+)\\s*)?$"); @@ -211,11 +330,12 @@ * @return Returns a new managed object path representing the * configuration root. */ public static ManagedObjectPath emptyPath() { public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() { return EMPTY_PATH; } /** * Returns a managed object path holding the value of the specified * string. @@ -227,29 +347,226 @@ * @throws IllegalArgumentException * If the string could not be parsed. */ public static ManagedObjectPath valueOf(String s) public static ManagedObjectPath<?, ?> valueOf(String s) throws IllegalArgumentException { return null; String ns = s.trim(); // Check for root special case. if (ns.equals("/")) { return EMPTY_PATH; } // Parse the elements. LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>(); AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn .getInstance(); if (!ns.startsWith("/")) { throw new IllegalArgumentException("Invalid path \"" + ns + "\": must begin with a \"/\""); } int start = 1; while (true) { // Get the next path element. int end; for (end = start; end < ns.length(); end++) { char c = ns.charAt(end); if (c == '/') { if (end == (ns.length() - 1)) { throw new IllegalArgumentException("Invalid path \"" + ns + "\": must not end with a trailing \"/\""); } if (ns.charAt(end + 1) == '/') { // Found an escaped forward slash. end++; } else { // Found the end of this path element. break; } } } // Get the next element. String es = ns.substring(start, end); Matcher m = PE_REGEXP.matcher(es); if (!m.matches()) { throw new IllegalArgumentException("Invalid path element \"" + es + "\" in path \"" + ns + "\""); } String relation = m.group(1); // Mandatory. String type = m.group(3); // Optional. String name = m.group(5); // Mandatory if relation is // instantiable. // Get the relation definition. RelationDefinition<?, ?> r; try { r = definition.getRelationDefinition(relation); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid path element \"" + es + "\" in path \"" + ns + "\": unknown relation \"" + relation + "\""); } // Append the next element. Element<?, ?> e = createElement(r, ns, es, type, name); elements.add(e); definition = e.getManagedObjectDefinition(); // Update start to point to the beginning of the next element. if (end < ns.length()) { // Skip to the beginning of the next element start = end + 1; } else { // We reached the end of the string. break; } } // Construct the new path. return create(elements, definition); } // Factory method required in order to allow generic wild-card // construction of new paths. private static <C extends ConfigurationClient, S extends Configuration> ManagedObjectPath<C, S> create( LinkedList<Element<?, ?>> elements, AbstractManagedObjectDefinition<C, S> definition) { return new ManagedObjectPath<C, S>(elements, definition); } // Decode an element. private static <C extends ConfigurationClient, S extends Configuration> Element<? extends C, ? extends S> createElement( RelationDefinition<C, S> r, String path, String element, String type, String name) { // First determine the managed object definition. AbstractManagedObjectDefinition<? extends C, ? extends S> d = null; if (type != null) { for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : r .getChildDefinition().getAllChildren()) { if (child.getName().equals(type)) { d = child; break; } } if (d == null) { throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path + "\": unknown sub-type \"" + type + "\""); } } else { d = r.getChildDefinition(); } if (r instanceof InstantiableRelationDefinition) { InstantiableRelationDefinition<C, S> ir = (InstantiableRelationDefinition<C, S>) r; if (name == null) { throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path + "\": no instance name for instantiable relation"); } return InstantiableElement.create(ir, d, name); } else if (r instanceof OptionalRelationDefinition) { OptionalRelationDefinition<C, S> or = (OptionalRelationDefinition<C, S>) r; if (name != null) { throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path + "\": instance name specified for optional relation"); } return OptionalElement.create(or, d); } else if (r instanceof SingletonRelationDefinition) { SingletonRelationDefinition<C, S> sr = (SingletonRelationDefinition<C, S>) r; if (name != null) { throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path + "\": instance name specified for singleton relation"); } return SingletonElement.create(sr, d); } else { throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path + "\": unsupported relation type"); } } // The last element in this path. private final AbstractManagedObjectDefinition<C, S> definition; // The list of path elements in this path. private final List<Element> elements; private final List<Element<?, ?>> elements; // Private constructor. private ManagedObjectPath(LinkedList<Element> elements) { private ManagedObjectPath(LinkedList<Element<?, ?>> elements, AbstractManagedObjectDefinition<C, S> definition) { this.elements = Collections.unmodifiableList(elements); this.definition = definition; } /** * Creates a new child managed object path beneath the provided * parent path. * parent path having the specified managed object definition. * * @param <M> * The type of client managed object configuration that the * child path references. * @param <N> * The type of server managed object configuration that the * child path references. * @param r * The instantiable relation referencing the child. * @param d * The managed object definition associated with the child * (must be a sub-type of the relation). * @param name * The relative name of the child managed object. * @return Returns a new child managed object path beneath the * provided parent path. */ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d, String name) { LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>( elements); celements.add(new InstantiableElement<M, N>(r, d, name)); return new ManagedObjectPath<M, N>(celements, d); } /** * Creates a new child managed object path beneath the provided * parent path using the relation's child managed object definition. * * @param <M> * The type of client managed object configuration that the * child path references. * @param <N> * The type of server managed object configuration that the * child path references. * @param r * The instantiable relation referencing the child. * @param name @@ -257,45 +574,116 @@ * @return Returns a new child managed object path beneath the * provided parent path. */ public ManagedObjectPath child( InstantiableRelationDefinition<?, ?> r, String name) { LinkedList<Element> celements = new LinkedList<Element>(elements); celements.add(new InstantiableElement(r, name)); return new ManagedObjectPath(celements); public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( InstantiableRelationDefinition<M, N> r, String name) { return child(r, r.getChildDefinition(), name); } /** * Creates a new child managed object path beneath the provided * parent path. * parent path having the specified managed object definition. * * @param <M> * The type of client managed object configuration that the * child path references. * @param <N> * The type of server managed object configuration that the * child path references. * @param r * The optional relation referencing the child. * @param d * The managed object definition associated with the child * (must be a sub-type of the relation). * @return Returns a new child managed object path beneath the * provided parent path. */ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( OptionalRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) { LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>( elements); celements.add(new OptionalElement<M, N>(r, d)); return new ManagedObjectPath<M, N>(celements, d); } /** * Creates a new child managed object path beneath the provided * parent path using the relation's child managed object definition. * * @param <M> * The type of client managed object configuration that the * child path references. * @param <N> * The type of server managed object configuration that the * child path references. * @param r * The optional relation referencing the child. * @return Returns a new child managed object path beneath the * provided parent path. */ public ManagedObjectPath child(OptionalRelationDefinition<?, ?> r) { LinkedList<Element> celements = new LinkedList<Element>(elements); celements.add(new OptionalElement(r)); return new ManagedObjectPath(celements); public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( OptionalRelationDefinition<M, N> r) { return child(r, r.getChildDefinition()); } /** * Creates a new child managed object path beneath the provided * parent path. * parent path having the specified managed object definition. * * @param <M> * The type of client managed object configuration that the * child path references. * @param <N> * The type of server managed object configuration that the * child path references. * @param r * The singleton relation referencing the child. * @param d * The managed object definition associated with the child * (must be a sub-type of the relation). * @return Returns a new child managed object path beneath the * provided parent path. */ public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( SingletonRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) { LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>( elements); celements.add(new SingletonElement<M, N>(r, d)); return new ManagedObjectPath<M, N>(celements, d); } /** * Creates a new child managed object path beneath the provided * parent path using the relation's child managed object definition. * * @param <M> * The type of client managed object configuration that the * child path references. * @param <N> * The type of server managed object configuration that the * child path references. * @param r * The singleton relation referencing the child. * @return Returns a new child managed object path beneath the * provided parent path. */ public ManagedObjectPath child(SingletonRelationDefinition<?, ?> r) { LinkedList<Element> celements = new LinkedList<Element>(elements); celements.add(new SingletonElement(r)); return new ManagedObjectPath(celements); public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( SingletonRelationDefinition<M, N> r) { return child(r, r.getChildDefinition()); } @@ -321,20 +709,14 @@ * Get the definition of the managed object referred to by this * path. * <p> * When the path is empty, the {@link RootCfgDefn} * is returned. * When the path is empty, the {@link RootCfgDefn} is returned. * * @return Returns the definition of the managed object referred to * by this path, or the {@link RootCfgDefn} * if the path is empty. * by this path, or the {@link RootCfgDefn} if the path is * empty. */ public AbstractManagedObjectDefinition<?, ?> getManagedObjectDefinition() { if (elements.isEmpty()) { return RootCfgDefn.getInstance(); } else { Element e = elements.get(elements.size() - 1); return e.getRelation().getChildDefinition(); } public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() { return definition; } @@ -362,6 +744,23 @@ /** * Creates a new parent managed object path representing the * immediate parent of this path. This method is a short-hand * for <code>parent(1)</code>. * * @return Returns a new parent managed object path representing the * immediate parent of this path. * @throws IllegalArgumentException * If this path does not have a parent (i.e. it is the * empty path). */ public ManagedObjectPath<?, ?> parent() throws IllegalArgumentException { return parent(1); } /** * Creates a new parent managed object path the specified number of * path elements above this path. * @@ -374,7 +773,7 @@ * If the offset is less than 0, or greater than the * number of path elements in this path. */ public ManagedObjectPath parent(int offset) public ManagedObjectPath<?, ?> parent(int offset) throws IllegalArgumentException { if (offset < 0) { throw new IllegalArgumentException("Negative offset"); @@ -390,9 +789,16 @@ return this; } LinkedList<Element> celements = new LinkedList<Element>(elements .subList(0, elements.size() - offset)); return new ManagedObjectPath(celements); // Return the empty path if the parent has zero elements. if (elements.size() == offset) { return emptyPath(); } LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>( elements.subList(0, elements.size() - offset)); AbstractManagedObjectDefinition<?, ?> definition = celements.getLast() .getManagedObjectDefinition(); return create(celements, definition); } @@ -409,7 +815,7 @@ * The managed object path serialization strategy. */ public void serialize(ManagedObjectPathSerializer serializer) { for (Element element : elements) { for (Element<?, ?> element : elements) { element.serialize(serializer); } } @@ -449,36 +855,14 @@ * @see #toString() */ public void toString(final StringBuilder builder) { // Use a simple serializer to create the contents. ManagedObjectPathSerializer serializer = new ManagedObjectPathSerializer() { public void appendManagedObjectPathElement( InstantiableRelationDefinition<?, ?> r, String name) { builder.append('/'); builder.append(r.getName()); builder.append('/'); builder.append(name); } public void appendManagedObjectPathElement( OptionalRelationDefinition<?, ?> r) { builder.append('/'); builder.append(r.getName()); } public void appendManagedObjectPathElement( SingletonRelationDefinition<?, ?> r) { builder.append('/'); builder.append(r.getName()); } }; serialize(serializer); if (isEmpty()) { // Special treatment of root configuration paths. builder.append('/'); } else { // Use a simple serializer to create the contents. ManagedObjectPathSerializer serializer = new StringSerializer(builder); serialize(serializer); } } } opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPathSerializer.java
@@ -31,48 +31,83 @@ /** * A strategy for serializing managed object paths. * <p> * This interface provides a generic means for serializing managed object paths * into application specific forms. For example, a JNDI client would use this * interface to construct <code>LdapName</code> objects from a path. * Similarly, on the server side, a serialization strategy is used to construct * <code>DN</code> instances from a path. * This interface provides a generic means for serializing managed * object paths into application specific forms. For example, a JNDI * client would use this interface to construct <code>LdapName</code> * objects from a path. Similarly, on the server side, a serialization * strategy is used to construct <code>DN</code> instances from a * path. * <p> * During serialization the serializer is invoked for each element in the * managed object path in big-endian order, starting from the root and * proceeding down to the leaf element. * During serialization the serializer is invoked for each element in * the managed object path in big-endian order, starting from the root * and proceeding down to the leaf element. */ public interface ManagedObjectPathSerializer { /** * Append a managed object path element identified by an instantiable relation * and an instance name. * Append a managed object path element identified by an * instantiable relation and an instance name. * * @param <C> * The type of client managed object configuration that * this path element references. * @param <S> * The type of server managed object configuration that * this path element references. * @param r * The instantiable relation. * @param d * The managed object definition. * @param name * The instance name. */ void appendManagedObjectPathElement(InstantiableRelationDefinition<?, ?> r, String name); <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d, String name); /** * Append a managed object path element identified by a optional relation. * Append a managed object path element identified by an optional * relation. * * @param <C> * The type of client managed object configuration that * this path element references. * @param <S> * The type of server managed object configuration that * this path element references. * @param r * The optional relation. * @param d * The managed object definition. */ void appendManagedObjectPathElement(OptionalRelationDefinition<?, ?> r); <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d); /** * Append a managed object path element identified by a singleton relation. * Append a managed object path element identified by a singleton * relation. * * @param <C> * The type of client managed object configuration that * this path element references. * @param <S> * The type of server managed object configuration that * this path element references. * @param r * The singleton relation. * @param d * The managed object definition. */ void appendManagedObjectPathElement(SingletonRelationDefinition<?, ?> r); <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d); } opendj-sdk/opends/src/server/org/opends/server/admin/client/ExampleIntrospection.java
@@ -32,17 +32,14 @@ import static org.opends.server.util.ServerConstants.PROPERTY_SERVER_ROOT; import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.opends.server.admin.AbstractManagedObjectDefinition; import org.opends.server.admin.ClassLoaderProvider; import org.opends.server.admin.AggregationRelationDefinition; import org.opends.server.admin.AttributeTypePropertyDefinition; import org.opends.server.admin.ClassLoaderProvider; import org.opends.server.admin.ClassPropertyDefinition; import org.opends.server.admin.InstantiableRelationDefinition; import org.opends.server.admin.ManagedObjectDefinition; @@ -136,7 +133,7 @@ RootCfgDefn d = RootCfgDefn.getInstance(); String operands = ""; for (RelationDefinition<?, ?> r : d.getRelationDefinitions()) { for (RelationDefinition<?, ?> r : d.getAllRelationDefinitions()) { r.accept(this, operands); } } @@ -316,22 +313,7 @@ private void processManagedObjectDefinition( AbstractManagedObjectDefinition<?, ?> parent, AbstractManagedObjectDefinition<?, ?> child, String operands) { Set<RelationDefinition<?, ?>> parentRelations; Set<RelationDefinition<?, ?>> childRelations; if (parent != null) { parentRelations = new HashSet<RelationDefinition<?, ?>>(parent .getRelationDefinitions()); } else { parentRelations = Collections.emptySet(); } // Only process relations not defined in parent. childRelations = new HashSet<RelationDefinition<?, ?>>(child .getRelationDefinitions()); childRelations.removeAll(parentRelations); for (RelationDefinition<?, ?> r : childRelations) { for (RelationDefinition<?, ?> r : child.getRelationDefinitions()) { r.accept(this, operands); } opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
@@ -154,8 +154,7 @@ * If an attempt was made to remove a mandatory property. * @throws IllegalArgumentException * If the specified property definition is not associated * with this managed object, or if the property is * read-only. * with this managed object. */ public <T> void setPropertyValue(PropertyDefinition<T> d, T value) throws IllegalPropertyValueException, @@ -191,8 +190,7 @@ * If an attempt was made to remove a mandatory property. * @throws IllegalArgumentException * If the specified property definition is not associated * with this managed object, or if the property is * read-only. * with this managed object. */ public <T> void setPropertyValues(PropertyDefinition<T> d, Collection<T> values) throws IllegalPropertyValueException, opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
@@ -434,7 +434,7 @@ new HashMap<PropertyDefinition, MyProperty>(); // Copy the properties from the provider. for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) { for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { createProperty(pd, p, i, properties, exceptions); } @@ -472,7 +472,7 @@ new HashMap<PropertyDefinition, MyProperty>(); // Copy the properties from the provider. for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) { for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { createProperty(pd, p, i, properties, exceptions); } @@ -692,7 +692,7 @@ * If an attempt was made to remove a mandatory property. * @throws IllegalArgumentException * If the specified property definition is not associated with this * managed object, or if the property is read-only. * managed object. */ public <T> void setPropertyValue(PropertyDefinition<T> d, T value) throws IllegalPropertyValueException, PropertyIsReadOnlyException, @@ -732,7 +732,7 @@ * If an attempt was made to remove a mandatory property. * @throws IllegalArgumentException * If the specified property definition is not associated with this * managed object, or if the property is read-only. * managed object. */ public <T> void setPropertyValues(PropertyDefinition<T> d, Collection<T> values) throws IllegalPropertyValueException, opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -128,7 +128,8 @@ public Collection<?> getDefaultPropertyValues( ManagedObjectPath path, String propertyName) throws OperationsException, PropertyNotFoundException { ManagedObject<?> mo = readEntry(dirContext, path, path ManagedObjectPath<?, ?> tmp = path; ManagedObject<?> mo = readEntry(dirContext, tmp, tmp .getManagedObjectDefinition()); ManagedObjectDefinition<?, ?> mod = mo .getManagedObjectDefinition(); @@ -202,7 +203,7 @@ ManagedObjectDefinition<?, ?> d) { ArrayList<String> attrIds = new ArrayList<String>(); for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) { for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { String attrId = LDAPProfile.getInstance().getAttributeName(d, pd); attrIds.add(attrId); @@ -348,7 +349,7 @@ private final DirContext dirContext; // The path associated with this managed object. private final ManagedObjectPath path; private final ManagedObjectPath<?, ?> path; // LDAP profile associated with this connection. private final LDAPProfile profile; @@ -382,7 +383,7 @@ ManagedObjectDefinition<C, ?> d = getManagedObjectDefinition(); LDAPChangeBuilder builder = new LDAPChangeBuilder(dirContext, path, d); for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) { for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { // FIXME: should throw an error when there are missing mandatory // properties. Property<?> p = properties.getProperty(pd); @@ -696,7 +697,7 @@ attributes.put(rdn.getType(), rdn.getValue().toString()); // Create the remaining attributes. for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) { for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { String attrID = profile.getAttributeName(d, pd); Attribute attribute = new BasicAttribute(attrID); encodeProperty(attribute, pd, properties); opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
@@ -35,6 +35,9 @@ import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import org.opends.server.admin.AbstractManagedObjectDefinition; import org.opends.server.admin.Configuration; import org.opends.server.admin.ConfigurationClient; import org.opends.server.admin.InstantiableRelationDefinition; import org.opends.server.admin.LDAPProfile; import org.opends.server.admin.ManagedObjectPath; @@ -106,8 +109,10 @@ /** * {@inheritDoc} */ public void appendManagedObjectPathElement( InstantiableRelationDefinition<?, ?> r, String name) { public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d, String name) { // Add the RDN sequence representing the relation. appendManagedObjectPathElement((RelationDefinition) r); @@ -146,8 +151,10 @@ /** * {@inheritDoc} */ public void appendManagedObjectPathElement( OptionalRelationDefinition<?, ?> r) { public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { // Add the RDN sequence representing the relation. appendManagedObjectPathElement((RelationDefinition) r); } @@ -157,8 +164,10 @@ /** * {@inheritDoc} */ public void appendManagedObjectPathElement( SingletonRelationDefinition<?, ?> r) { public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { // Add the RDN sequence representing the relation. appendManagedObjectPathElement((RelationDefinition) r); } opendj-sdk/opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
@@ -58,7 +58,7 @@ AbstractConfigListenerAdaptor implements ConfigAddListener { // The managed object path of the parent. private final ManagedObjectPath path; private final ManagedObjectPath<?, ?> path; // The instantiable relation. private final InstantiableRelationDefinition<?, S> instantiableRelation; opendj-sdk/opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
@@ -60,7 +60,7 @@ ConfigDeleteListener { // The managed object path of the parent. private final ManagedObjectPath path; private final ManagedObjectPath<?, ?> path; // The instantiable relation. private final InstantiableRelationDefinition<?, S> instantiableRelation; opendj-sdk/opends/src/server/org/opends/server/admin/server/DNBuilder.java
@@ -29,6 +29,9 @@ import org.opends.server.admin.AbstractManagedObjectDefinition; import org.opends.server.admin.Configuration; import org.opends.server.admin.ConfigurationClient; import org.opends.server.admin.InstantiableRelationDefinition; import org.opends.server.admin.LDAPProfile; import org.opends.server.admin.ManagedObjectPath; @@ -120,8 +123,10 @@ /** * {@inheritDoc} */ public void appendManagedObjectPathElement( InstantiableRelationDefinition<?, ?> r, String name) { public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d, String name) { // Add the RDN sequence representing the relation. appendManagedObjectPathElement((RelationDefinition) r); @@ -155,8 +160,10 @@ /** * {@inheritDoc} */ public void appendManagedObjectPathElement( OptionalRelationDefinition<?, ?> r) { public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { // Add the RDN sequence representing the relation. appendManagedObjectPathElement((RelationDefinition) r); } @@ -166,8 +173,10 @@ /** * {@inheritDoc} */ public void appendManagedObjectPathElement( SingletonRelationDefinition<?, ?> r) { public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { // Add the RDN sequence representing the relation. appendManagedObjectPathElement((RelationDefinition) r); } opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
@@ -96,7 +96,7 @@ InheritedDefaultValueProvider { // The base path. private final ManagedObjectPath path; private final ManagedObjectPath<?, ?> path; @@ -131,7 +131,8 @@ throw new ManagedObjectNotFoundException(); } ServerManagedObject<?> mo = decode(path, path ManagedObjectPath<?, ?> tmp = path; ServerManagedObject<?> mo = decode(tmp, tmp .getManagedObjectDefinition(), configEntry); ManagedObjectDefinition<?, ?> mod = mo .getManagedObjectDefinition(); @@ -295,7 +296,7 @@ // The managed object path identifying this managed object's // location. private final ManagedObjectPath path; private final ManagedObjectPath<?, ?> path; // The managed object's properties. private final PropertySet properties; opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
New file @@ -0,0 +1,240 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2007 Sun Microsystems, Inc. */ package org.opends.server.admin; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.opends.server.TestCaseUtils; import org.opends.server.admin.std.client.ConnectionHandlerCfgClient; import org.opends.server.admin.std.client.GlobalCfgClient; import org.opends.server.admin.std.client.LDAPConnectionHandlerCfgClient; import org.opends.server.admin.std.meta.ConnectionHandlerCfgDefn; import org.opends.server.admin.std.meta.GlobalCfgDefn; import org.opends.server.admin.std.meta.LDAPConnectionHandlerCfgDefn; import org.opends.server.admin.std.meta.MultimasterDomainCfgDefn; import org.opends.server.admin.std.meta.MultimasterSynchronizationProviderCfgDefn; import org.opends.server.admin.std.meta.RootCfgDefn; import org.opends.server.admin.std.server.ConnectionHandlerCfg; import org.opends.server.admin.std.server.GlobalCfg; import org.opends.server.admin.std.server.LDAPConnectionHandlerCfg; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * ManagedObjectPath test cases. */ public class ManagedObjectPathTest { /** * Sets up tests * * @throws Exception * If the server could not be initialized. */ @BeforeClass public void setUp() throws Exception { // This test suite depends on having the schema available, so // we'll start the server. TestCaseUtils.startServer(); } /** * Tests that the empty path is empty. */ @Test public void testEmptyPathIsEmpty() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); assertTrue(path.isEmpty()); } /** * Tests that the empty path has a size of zero. */ @Test public void testEmptyPathHasZeroElements() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); assertEquals(path.size(), 0); } /** * Tests that the empty path has no parent. */ @Test(expectedExceptions = IllegalArgumentException.class) public void testEmptyPathHasNoParent() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); path.parent(); } /** * Tests that the empty path represents the root configuration. */ @Test public void testEmptyPathIsRootConfiguration() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); assertEquals(path.getManagedObjectDefinition(), RootCfgDefn.getInstance()); } /** * Tests that the empty path has a string representation of "/". */ @Test public void testEmptyPathString() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); assertEquals(path.toString(), "/"); } /** * Tests that the empty path can be decoded. */ @Test public void testEmptyPathDecode() { ManagedObjectPath<?, ?> path = ManagedObjectPath.valueOf("/"); assertEquals(path, ManagedObjectPath.emptyPath()); } /** * Tests singleton child creation. */ @Test public void testSingletonChild() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); ManagedObjectPath<GlobalCfgClient, GlobalCfg> child = path .child(RootCfgDefn.getInstance() .getGlobalConfigurationRelationDefinition()); assertFalse(child.isEmpty()); assertEquals(child.size(), 1); assertEquals(child.parent(), path); assertEquals(child.getManagedObjectDefinition(), GlobalCfgDefn .getInstance()); assertEquals(child.toString(), "/relation=global-configuration"); assertEquals(child, ManagedObjectPath .valueOf("/relation=global-configuration")); } /** * Tests instantiable child creation. */ @Test public void testInstantiableChild() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); ManagedObjectPath<ConnectionHandlerCfgClient, ConnectionHandlerCfg> child = path .child(RootCfgDefn.getInstance() .getConnectionHandlersRelationDefinition(), "LDAP connection handler"); assertFalse(child.isEmpty()); assertEquals(child.size(), 1); assertEquals(child.parent(), path); assertEquals(child.getManagedObjectDefinition(), ConnectionHandlerCfgDefn .getInstance()); assertEquals(child.toString(), "/relation=connection-handler+name=LDAP connection handler"); assertEquals(child, ManagedObjectPath .valueOf("/relation=connection-handler+name=LDAP connection handler")); } /** * Tests instantiable child creation with specific sub-type. */ @Test public void testInstantiableChildWithSubtype() { ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath(); ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child = path .child(RootCfgDefn.getInstance() .getConnectionHandlersRelationDefinition(), LDAPConnectionHandlerCfgDefn.getInstance(), "LDAP connection handler"); assertFalse(child.isEmpty()); assertEquals(child.size(), 1); assertEquals(child.parent(), path); assertEquals(child.getManagedObjectDefinition(), LDAPConnectionHandlerCfgDefn.getInstance()); assertEquals( child.toString(), "/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler"); assertEquals( child, ManagedObjectPath .valueOf("/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler")); } /** * Tests instantiable child creation with multiple levels. */ @Test public void testInstantiableMultipleLevels() { ManagedObjectPath<?, ?> root = ManagedObjectPath.emptyPath(); ManagedObjectPath<?, ?> mmr = root.child(RootCfgDefn.getInstance() .getSynchronizationProvidersRelationDefinition(), MultimasterSynchronizationProviderCfgDefn.getInstance(), "MMR"); ManagedObjectPath<?, ?> domain = mmr.child( MultimasterSynchronizationProviderCfgDefn.getInstance() .getMultimasterDomainsRelationDefinition(), "Domain"); assertFalse(domain.isEmpty()); assertEquals(domain.size(), 2); assertEquals(domain.parent(), mmr); assertEquals(domain.parent(2), root); assertEquals(domain.getManagedObjectDefinition(), MultimasterDomainCfgDefn .getInstance()); assertEquals( domain.toString(), "/relation=synchronization-provider+type=multimaster-synchronization-provider+name=MMR/relation=multimaster-domain+name=Domain"); assertEquals( domain, ManagedObjectPath .valueOf("/relation=synchronization-provider+type=multimaster-synchronization-provider+name=MMR/relation=multimaster-domain+name=Domain")); } }