From 95df5cfdba474acb03076953e992b898fbb277a8 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Mon, 02 Feb 2009 23:37:54 +0000
Subject: [PATCH] Fix issue 3734 - Make network group policies extensible.
---
opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 320 insertions(+), 26 deletions(-)
diff --git a/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java b/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
index 735e3ef..1737bf8 100644
--- a/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
+++ b/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2007-2008 Sun Microsystems, Inc.
+ * Copyright 2007-2009 Sun Microsystems, Inc.
*/
package org.opends.server.tools.dsconfig;
@@ -40,10 +40,10 @@
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
+import java.util.SortedMap;
+import java.util.TreeMap;
import org.opends.messages.Message;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.Configuration;
@@ -59,6 +59,8 @@
import org.opends.server.admin.OptionalRelationDefinition;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.PropertyDefinitionUsageBuilder;
+import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.SetRelationDefinition;
import org.opends.server.admin.SingletonRelationDefinition;
import org.opends.server.admin.SizeUnit;
import org.opends.server.admin.Tag;
@@ -256,6 +258,100 @@
*/
public <C extends ConfigurationClient, S extends Configuration>
void appendManagedObjectPathElement(
+ SetRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ if (result.isSuccess()) {
+ // We should ignore the "template" name here and use a path
+ // argument.
+ String childName = args.get(argIndex++);
+
+ try {
+ // If the name is null then we must be interactive - so let
+ // the user choose.
+ if (childName == null) {
+ try {
+ MenuResult<String> sresult = readChildName(app,
+ result.getValue(), r, d);
+
+ if (sresult.isCancel()) {
+ result = MenuResult.cancel();
+ return;
+ } else if (sresult.isQuit()) {
+ result = MenuResult.quit();
+ return;
+ } else {
+ childName = sresult.getValue();
+ }
+ } catch (CLIException e) {
+ clie = e;
+ result = MenuResult.quit();
+ return;
+ }
+ } else if (childName.trim().length() == 0) {
+ IllegalManagedObjectNameException e =
+ new IllegalManagedObjectNameException(childName);
+ clie = ArgumentExceptionFactory
+ .adaptIllegalManagedObjectNameException(e, d);
+ result = MenuResult.quit();
+ return;
+ } else {
+ String name = childName.trim();
+ SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>>
+ types = getSubTypes(d);
+ ManagedObjectDefinition<?, ?> cd = types.get(name);
+ if (cd == null) {
+ // The name must be invalid.
+ String typeUsage = getSubTypesUsage(d);
+ Message msg = ERR_DSCFG_ERROR_SUB_TYPE_UNRECOGNIZED.get(
+ name, r.getUserFriendlyName(), typeUsage);
+ clie = new CLIException(msg);
+ result = MenuResult.quit();
+ return;
+ } else {
+ childName = cd.getName();
+ }
+ }
+
+ ManagedObject<?> child = result.getValue().getChild(r, childName);
+
+ // Check that child is a sub-type of the specified
+ // definition.
+ if (!child.getManagedObjectDefinition().isChildOf(d)) {
+ clie = ArgumentExceptionFactory.wrongManagedObjectType(r, child
+ .getManagedObjectDefinition(), getSubCommand().getName());
+ result = MenuResult.quit();
+ } else {
+ result = MenuResult.<ManagedObject<?>>success(child);
+ }
+ } catch (DefinitionDecodingException e) {
+ dde = e;
+ result = MenuResult.quit();
+ } catch (ManagedObjectDecodingException e) {
+ mode = e;
+ result = MenuResult.quit();
+ } catch (AuthorizationException e) {
+ authze = e;
+ result = MenuResult.quit();
+ } catch (ManagedObjectNotFoundException e) {
+ monfe = e;
+ result = MenuResult.quit();
+ } catch (ConcurrentModificationException e) {
+ cme = e;
+ result = MenuResult.quit();
+ } catch (CommunicationException e) {
+ ce = e;
+ result = MenuResult.quit();
+ }
+ }
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
SingletonRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
if (result.isSuccess()) {
@@ -513,6 +609,38 @@
*/
public <C extends ConfigurationClient, S extends Configuration>
void appendManagedObjectPathElement(
+ SetRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ sz--;
+
+ // The name of the managed object is determined from its type, so
+ // we don't need this argument.
+ if (isCreate && sz == 0) {
+ return;
+ }
+
+ String argName = CLIProfile.getInstance().getNamingArgument(r);
+ StringArgument arg;
+
+ try {
+ arg =
+ new StringArgument(argName, null, argName, false, true,
+ INFO_NAME_PLACEHOLDER.get(),
+ INFO_DSCFG_DESCRIPTION_NAME.get(d.getUserFriendlyName()));
+ subCommand.addArgument(arg);
+ arguments.add(arg);
+ } catch (ArgumentException e) {
+ this.e = e;
+ }
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
SingletonRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
sz--;
@@ -997,21 +1125,22 @@
* @param parent
* The parent managed object.
* @param r
- * The relation between the parent and the children.
+ * The relation between the parent and the children, must be
+ * a set or instantiable relation.
* @param d
* The type of child managed object to choose from.
- * @return Returns a {@link MenuResult#success()} containing the
- * name of the managed object that the user selected, or
- * {@link MenuResult#quit()}, or
- * {@link MenuResult#cancel()}, if the sub-command was run
- * interactive and the user chose to quit or cancel.
+ * @return Returns a {@link MenuResult#success()} containing the name
+ * of the managed object that the user selected, or
+ * {@link MenuResult#quit()}, or {@link MenuResult#cancel()},
+ * if the sub-command was run interactive and the user chose
+ * to quit or cancel.
* @throws CommunicationException
* If the server cannot be contacted.
* @throws ConcurrentModificationException
* If the parent managed object has been deleted.
* @throws AuthorizationException
- * If the children cannot be listed due to an
- * authorization failure.
+ * If the children cannot be listed due to an authorization
+ * failure.
* @throws CLIException
* If the user input can be read from the console or if
* there are no children.
@@ -1019,7 +1148,7 @@
protected final <C extends ConfigurationClient, S extends Configuration>
MenuResult<String> readChildName(
ConsoleApplication app, ManagedObject<?> parent,
- InstantiableRelationDefinition<C, S> r,
+ RelationDefinition<C, S> r,
AbstractManagedObjectDefinition<? extends C, ? extends S> d)
throws AuthorizationException, ConcurrentModificationException,
CommunicationException, CLIException {
@@ -1031,14 +1160,25 @@
app.println();
// Filter out advanced and hidden types if required.
- String[] childNames = parent.listChildren(r, d);
- SortedSet<String> children = new TreeSet<String>(
+ String[] childNames;
+ if (r instanceof InstantiableRelationDefinition) {
+ childNames =
+ parent.listChildren((InstantiableRelationDefinition<C,S>)r, d);
+ } else {
+ childNames = parent.listChildren((SetRelationDefinition<C,S>)r, d);
+ }
+ SortedMap<String, String> children = new TreeMap<String, String>(
String.CASE_INSENSITIVE_ORDER);
for (String childName : childNames) {
ManagedObject<?> child;
try {
- child = parent.getChild(r, childName);
+ if (r instanceof InstantiableRelationDefinition) {
+ child = parent.getChild((InstantiableRelationDefinition<C,S>)r,
+ childName);
+ } else {
+ child = parent.getChild((SetRelationDefinition<C,S>)r, childName);
+ }
ManagedObjectDefinition<?, ?> cd = child.getManagedObjectDefinition();
@@ -1051,13 +1191,18 @@
continue;
}
- children.add(childName);
+ if (r instanceof InstantiableRelationDefinition) {
+ children.put(childName, childName);
+ } else {
+ // For sets the RDN is the type string, the ufn is more friendly.
+ children.put(cd.getUserFriendlyName().toString(), childName);
+ }
} catch (DefinitionDecodingException e) {
// Add it anyway: maybe the user is trying to fix the problem.
- children.add(childName);
+ children.put(childName, childName);
} catch (ManagedObjectDecodingException e) {
// Add it anyway: maybe the user is trying to fix the problem.
- children.add(childName);
+ children.put(childName, childName);
} catch (ManagedObjectNotFoundException e) {
// Skip it - the managed object has been concurrently removed.
}
@@ -1075,7 +1220,7 @@
// Only one option available so confirm that the user wishes to
// access it.
Message msg = INFO_DSCFG_FINDER_PROMPT_SINGLE.get(
- d.getUserFriendlyName(), children.first());
+ d.getUserFriendlyName(), children.firstKey());
if (app.confirmAction(msg, true)) {
try
{
@@ -1083,7 +1228,18 @@
StringArgument arg = new StringArgument(argName, null, argName, false,
true, INFO_NAME_PLACEHOLDER.get(),
INFO_DSCFG_DESCRIPTION_NAME_CREATE.get(d.getUserFriendlyName()));
- arg.addValue(children.first());
+ if (r instanceof InstantiableRelationDefinition) {
+ arg.addValue(children.get(children.firstKey()));
+ } else {
+ // Set relation: need the short type name.
+ String longName = children.firstKey();
+ try {
+ AbstractManagedObjectDefinition<?,?> cd = d.getChild(longName);
+ arg.addValue(getShortTypeName(r.getChildDefinition(), cd));
+ } catch (IllegalArgumentException e) {
+ arg.addValue(children.get(children.firstKey()));
+ }
+ }
getCommandBuilder().addArgument(arg);
}
catch (Throwable t)
@@ -1091,7 +1247,7 @@
// Bug
new RuntimeException("Unexpected exception: "+t, t);
}
- return MenuResult.success(children.first());
+ return MenuResult.success(children.get(children.firstKey()));
} else {
return MenuResult.cancel();
}
@@ -1103,9 +1259,9 @@
builder.setPrompt(INFO_DSCFG_FINDER_PROMPT_MANY.get(d
.getUserFriendlyName()));
- for (String child : children) {
- Message option = Message.raw("%s", child);
- builder.addNumberedOption(option, MenuResult.success(child));
+ for (Map.Entry<String, String> child : children.entrySet()) {
+ Message option = Message.raw("%s", child.getKey());
+ builder.addNumberedOption(option, MenuResult.success(child.getValue()));
}
if (app.isMenuDrivenMode()) {
@@ -1121,7 +1277,18 @@
StringArgument arg = new StringArgument(argName, null, argName, false,
true, INFO_NAME_PLACEHOLDER.get(),
INFO_DSCFG_DESCRIPTION_NAME_CREATE.get(d.getUserFriendlyName()));
- arg.addValue(result.getValue());
+ if (r instanceof InstantiableRelationDefinition) {
+ arg.addValue(result.getValue());
+ } else {
+ // Set relation: need the short type name.
+ String longName = result.getValue();
+ try {
+ AbstractManagedObjectDefinition<?, ?> cd = d.getChild(longName);
+ arg.addValue(getShortTypeName(r.getChildDefinition(), cd));
+ } catch (IllegalArgumentException e) {
+ arg.addValue(children.get(result.getValue()));
+ }
+ }
getCommandBuilder().addArgument(arg);
}
catch (Throwable t)
@@ -1248,4 +1415,131 @@
}
return value;
}
+
+
+
+ /**
+ * Returns a mapping of subordinate managed object type argument
+ * values to their corresponding managed object definitions for the
+ * provided managed object definition.
+ *
+ * @param <C>
+ * The type of client configuration.
+ * @param <S>
+ * The type of server configuration.
+ * @param d
+ * The managed object definition.
+ * @return A mapping of managed object type argument values to their
+ * corresponding managed object definitions.
+ */
+ @SuppressWarnings("unchecked")
+ protected static <C extends ConfigurationClient, S extends Configuration>
+ SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>>
+ getSubTypes(AbstractManagedObjectDefinition<C, S> d) {
+ SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>> map;
+ map =
+ new TreeMap<String, ManagedObjectDefinition<? extends C, ? extends S>>();
+
+ // If the top-level definition is instantiable, we use the value
+ // "generic" or "custom".
+ if (!d.hasOption(ManagedObjectOption.HIDDEN)) {
+ if (d instanceof ManagedObjectDefinition) {
+ ManagedObjectDefinition<? extends C, ? extends S> mod =
+ (ManagedObjectDefinition<? extends C, ? extends S>) d;
+ map.put(getShortTypeName(d, mod), mod);
+ }
+ }
+
+ // Process its sub-definitions.
+ for (AbstractManagedObjectDefinition<? extends C, ? extends S> c : d
+ .getAllChildren()) {
+ if (d.hasOption(ManagedObjectOption.HIDDEN)) {
+ continue;
+ }
+
+ if (c instanceof ManagedObjectDefinition) {
+ ManagedObjectDefinition<? extends C, ? extends S> mod =
+ (ManagedObjectDefinition<? extends C, ? extends S>) c;
+ map.put(getShortTypeName(d, mod), mod);
+ }
+ }
+
+ return map;
+ }
+
+
+
+ /**
+ * Returns the type short name for a child managed object definition.
+ *
+ * @param <C>
+ * The type of client configuration.
+ * @param <S>
+ * The type of server configuration.
+ * @param d
+ * The top level parent definition.
+ * @param c
+ * The child definition.
+ * @return The type short name.
+ */
+ protected static <C extends ConfigurationClient, S extends Configuration>
+ String getShortTypeName(
+ AbstractManagedObjectDefinition<C,S> d,
+ AbstractManagedObjectDefinition<?, ?> c) {
+ if (c == d) {
+ // This is the top-level definition, so use the value "generic" or
+ // "custom".
+ if (CLIProfile.getInstance().isForCustomization(c)) {
+ return DSConfig.CUSTOM_TYPE;
+ } else {
+ return DSConfig.GENERIC_TYPE;
+ }
+ } else {
+ // It's a child definition.
+ String suffix = "-" + d.getName();
+
+ // For the type name we shorten it, if possible, by stripping
+ // off the trailing part of the name which matches the
+ // base-type.
+ String name = c.getName();
+ if (name.endsWith(suffix)) {
+ name = name.substring(0, name.length() - suffix.length());
+ }
+
+ // If this type is intended for customization, prefix it with
+ // "custom".
+ if (CLIProfile.getInstance().isForCustomization(c)) {
+ name = String.format("%s-%s", DSConfig.CUSTOM_TYPE, name);
+ }
+
+ return name;
+ }
+ }
+
+
+
+ /**
+ * Returns a usage string representing the list of possible types for
+ * the provided managed object definition.
+ *
+ * @param d
+ * The managed object definition.
+ * @return A usage string representing the list of possible types for
+ * the provided managed object definition.
+ */
+ protected static String getSubTypesUsage(
+ AbstractManagedObjectDefinition<?, ?> d) {
+ // Build the -t option usage.
+ SortedMap<String, ?> types = getSubTypes(d);
+ StringBuilder builder = new StringBuilder();
+ boolean isFirst = true;
+ for (String s : types.keySet()) {
+ if (!isFirst) {
+ builder.append(" | ");
+ }
+ builder.append(s);
+ isFirst = false;
+ }
+ return builder.toString();
+ }
}
--
Gitblit v1.10.0