From 54c2799f45256fef4a981fa2a6a7c97a9708ac8b Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 26 Jul 2007 12:01:44 +0000
Subject: [PATCH] Partial fix for issue 1831 - dsconfig interactive mode.
---
opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java | 164 ++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 134 insertions(+), 30 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 a82d0d6..ac32ec1 100644
--- a/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
+++ b/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
@@ -82,12 +82,10 @@
* A path serializer which is used to retrieve a managed object
* based on a path and a list of path arguments.
*/
- private static class ManagedObjectFinder implements
- ManagedObjectPathSerializer {
+ private class ManagedObjectFinder implements ManagedObjectPathSerializer {
// Any argument exception that was caught when attempting to find
- // the
- // managed object.
+ // the managed object.
private ArgumentException ae;
// The index of the next path argument to be retrieved.
@@ -103,8 +101,7 @@
private ConcurrentModificationException cme;
// Any operation exception that was caught when attempting to find
- // the
- // managed object.
+ // the managed object.
private DefinitionDecodingException dde;
// Flag indicating whether or not an exception occurred during
@@ -133,6 +130,18 @@
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 {
+ childName = readChildName(managedObject, r, d);
+ } catch (ArgumentException e) {
+ ae = e;
+ gotException = true;
+ return;
+ }
+ }
+
ManagedObject<?> child = managedObject.getChild(r, childName);
// Check that child is a sub-type of the specified
@@ -377,14 +386,14 @@
// arguments.
private ArgumentException e = null;
- // The sub-command.
- private final SubCommand subCommand;
-
// Indicates whether the sub-command is a create-xxx
// sub-command, in which case the final path element will
// have different usage information.
private final boolean isCreate;
+ // The sub-command.
+ private final SubCommand subCommand;
+
// The number of path elements to expect.
private int sz;
@@ -435,17 +444,17 @@
PropertyDefinitionUsageBuilder b =
new PropertyDefinitionUsageBuilder(false);
String usage = "{" + b.getUsage(pd) + "}";
- arg = new StringArgument(argName, null, argName, true, true, usage,
- MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT, d
+ arg = new StringArgument(argName, null, argName, false, true,
+ usage, MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT, d
.getUserFriendlyName(), pd.getName(), pd.getSynopsis());
} else {
- arg = new StringArgument(argName, null, argName, true, true,
+ arg = new StringArgument(argName, null, argName, false, true,
"{NAME}", MSGID_DSCFG_DESCRIPTION_NAME_CREATE, d
.getUserFriendlyName());
}
} else {
// A normal naming argument.
- arg = new StringArgument(argName, null, argName, true, true,
+ arg = new StringArgument(argName, null, argName, false, true,
"{NAME}", MSGID_DSCFG_DESCRIPTION_NAME, d.getUserFriendlyName());
}
subCommand.addArgument(arg);
@@ -534,6 +543,9 @@
// The argument which should be used to request advanced mode.
private BooleanArgument advancedModeArgument;
+ // The application instance.
+ private final ConsoleApplication app;
+
// The argument which should be used to specify zero or more
// property names.
private StringArgument propertyArgument;
@@ -554,9 +566,12 @@
/**
* Create a new sub-command handler.
+ *
+ * @param app
+ * The application instance.
*/
- protected SubCommandHandler() {
- // No implementation required.
+ protected SubCommandHandler(ConsoleApplication app) {
+ this.app = app;
}
@@ -585,12 +600,6 @@
/**
* Run this sub-command handler.
*
- * @param app
- * The application.
- * @param out
- * The application output stream.
- * @param err
- * The application error stream.
* @return Returns zero if the sub-command completed successfully or
* non-zero if it did not.
* @throws ArgumentException
@@ -599,8 +608,7 @@
* @throws ClientException
* If the management context could not be created.
*/
- public abstract int run(DSConfig app, PrintStream out, PrintStream err)
- throws ArgumentException, ClientException;
+ public abstract int run() throws ArgumentException, ClientException;
@@ -685,11 +693,20 @@
/**
+ * Gets the console application instance.
+ *
+ * @return Returns the console application instance.
+ */
+ protected final ConsoleApplication getConsoleApplication() {
+ return app;
+ }
+
+
+
+ /**
* Get the managed object referenced by the provided managed object
* path.
*
- * @param context
- * The management context.
* @param path
* The managed object path.
* @param args
@@ -718,15 +735,17 @@
* @throws ArgumentException
* If one of the naming arguments referenced a managed
* object of the wrong type.
+ * @throws ClientException
+ * If the management context could not be created.
*/
- protected final ManagedObject<?> getManagedObject(ManagementContext context,
+ protected final ManagedObject<?> getManagedObject(
ManagedObjectPath<?, ?> path, List<String> args)
throws ArgumentException, AuthorizationException,
DefinitionDecodingException, ManagedObjectDecodingException,
CommunicationException, ConcurrentModificationException,
- ManagedObjectNotFoundException {
+ ManagedObjectNotFoundException, ClientException {
ManagedObjectFinder finder = new ManagedObjectFinder();
- return finder.find(context, path, args);
+ return finder.find(app.getManagementContext(), path, args);
}
@@ -737,12 +756,22 @@
* @param namingArgs
* The naming arguments.
* @return Returns the values of the naming arguments.
+ * @throws ArgumentException
+ * If one of the naming arguments is missing and the
+ * application is non-interactive.
*/
protected final List<String> getNamingArgValues(
- List<StringArgument> namingArgs) {
+ List<StringArgument> namingArgs) throws ArgumentException {
ArrayList<String> values = new ArrayList<String>(namingArgs.size());
for (StringArgument arg : namingArgs) {
- values.add(arg.getValue());
+ String value = arg.getValue();
+
+ if (value == null && !app.isInteractive()) {
+ throw ArgumentExceptionFactory
+ .missingMandatoryNonInteractiveArgument(arg);
+ } else {
+ values.add(value);
+ }
}
return values;
}
@@ -854,6 +883,81 @@
/**
+ * Interactively prompts the user to select from a choice of child
+ * managed objects.
+ * <p>
+ * This method will adapt according to the available choice. For
+ * example, if there is only one choice, then a question will be
+ * asked. If there are no children then an
+ * <code>ArgumentException</code> will be thrown.
+ *
+ * @param <C>
+ * The type of child client configuration.
+ * @param <S>
+ * The type of child server configuration.
+ * @param parent
+ * The parent managed object.
+ * @param r
+ * The relation between the parent and the children.
+ * @param d
+ * The type of child managed object to choose from.
+ * @return Returns the name of the managed object that the user
+ * selected.
+ * @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.
+ * @throws ArgumentException
+ * If the user input can be read from the console or if
+ * there are no children.
+ */
+ protected final <C extends ConfigurationClient, S extends Configuration>
+ String readChildName(ManagedObject<?> parent,
+ InstantiableRelationDefinition<C, S> r,
+ AbstractManagedObjectDefinition<? extends C, ? extends S> d)
+ throws AuthorizationException, ConcurrentModificationException,
+ CommunicationException, ArgumentException {
+ if (d == null) {
+ d = r.getChildDefinition();
+ }
+
+ String[] children = parent.listChildren(r, d);
+ switch (children.length) {
+ case 0: {
+ // No options available - abort.
+ int msgID = MSGID_DSCFG_ERROR_FINDER_NO_CHILDREN;
+ String msg = getMessage(msgID, d.getUserFriendlyPluralName());
+ throw new ArgumentException(msgID, msg);
+ }
+ case 1: {
+ // Only one option available so confirm that the user wishes to
+ // access it.
+ int msgID = MSGID_DSCFG_FINDER_PROMPT_SINGLE;
+ String msg = getMessage(msgID, d.getUserFriendlyName(), children[0]);
+ if (getConsoleApplication().confirmAction(msg)) {
+ return children[0];
+ } else {
+ msgID = MSGID_DSCFG_ERROR_FINDER_SINGLE_CHILD_REJECTED;
+ msg = getMessage(msgID, d.getUserFriendlyName());
+ throw new ArgumentException(msgID, msg);
+ }
+ }
+ default: {
+ // Display a menu.
+ List<String> choices = Arrays.asList(children);
+ int msgID = MSGID_DSCFG_FINDER_PROMPT_MANY;
+ String msg = getMessage(msgID, d.getUserFriendlyName());
+ return getConsoleApplication().readChoice(msg, choices, choices, null);
+ }
+ }
+ }
+
+
+
+ /**
* Registers the advanced mode argument with the sub-command.
*
* @param subCommand
--
Gitblit v1.10.0