From 4ffd9fe47a44245d8a9f579e6e22bea655f97bbd Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Wed, 29 Aug 2007 14:40:34 +0000
Subject: [PATCH] Fix issue 1831: dsconfig interactive mode.
---
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java | 323 ++++++++++++++++++++++++++++++++++-------------------
1 files changed, 209 insertions(+), 114 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
index 71ebdbd..61aff03 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
@@ -25,11 +25,10 @@
* Portions Copyright 2007 Sun Microsystems, Inc.
*/
package org.opends.server.tools.dsconfig;
-import org.opends.messages.Message;
-import static org.opends.messages.ToolMessages.*;
+import static org.opends.messages.DSConfigMessages.*;
import java.io.PrintStream;
import java.util.ArrayList;
@@ -42,6 +41,7 @@
import java.util.List;
import java.util.Set;
+import org.opends.messages.Message;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ConfigurationClient;
@@ -69,6 +69,11 @@
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.SubCommand;
+import org.opends.server.util.cli.CLIException;
+import org.opends.server.util.cli.ConsoleApplication;
+import org.opends.server.util.cli.Menu;
+import org.opends.server.util.cli.MenuBuilder;
+import org.opends.server.util.cli.MenuResult;
import org.opends.server.util.table.TabSeparatedTablePrinter;
import org.opends.server.util.table.TablePrinter;
@@ -77,7 +82,7 @@
/**
* An interface for sub-command implementations.
*/
-abstract class SubCommandHandler {
+abstract class SubCommandHandler implements Comparable<SubCommandHandler> {
/**
* A path serializer which is used to retrieve a managed object
@@ -85,9 +90,8 @@
*/
private class ManagedObjectFinder implements ManagedObjectPathSerializer {
- // Any argument exception that was caught when attempting to find
- // the managed object.
- private ArgumentException ae;
+ // The console application.
+ private ConsoleApplication app;
// The index of the next path argument to be retrieved.
private int argIndex;
@@ -99,23 +103,23 @@
private CommunicationException ce;
+ // Any CLI exception that was caught when attempting to find
+ // the managed object.
+ private CLIException clie;
+
private ConcurrentModificationException cme;
// Any operation exception that was caught when attempting to find
// the managed object.
private DefinitionDecodingException dde;
- // Flag indicating whether or not an exception occurred during
- // retrieval.
- private boolean gotException;
-
- // The last managed object retrieved.
- private ManagedObject<?> managedObject;
-
private ManagedObjectDecodingException mode;
private ManagedObjectNotFoundException monfe;
+ // The current result.
+ private MenuResult<ManagedObject<?>> result;
+
/**
@@ -125,7 +129,7 @@
void appendManagedObjectPathElement(
InstantiableRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d, String name) {
- if (!gotException) {
+ if (result.isSuccess()) {
// We should ignore the "template" name here and use a path
// argument.
String childName = args.get(argIndex++);
@@ -135,50 +139,61 @@
// the user choose.
if (childName == null) {
try {
- childName = readChildName(managedObject, r, d);
- } catch (ArgumentException e) {
- ae = e;
- gotException = true;
+ 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);
- ae = ArgumentExceptionFactory
+ clie = ArgumentExceptionFactory
.adaptIllegalManagedObjectNameException(e, d);
- gotException = true;
+ result = MenuResult.quit();
return;
}
- ManagedObject<?> child = managedObject.getChild(r, childName);
+ ManagedObject<?> child = result.getValue().getChild(r, childName);
// Check that child is a sub-type of the specified
// definition.
if (!child.getManagedObjectDefinition().isChildOf(d)) {
- ae = ArgumentExceptionFactory.wrongManagedObjectType(r, child
+ clie = ArgumentExceptionFactory.wrongManagedObjectType(r, child
.getManagedObjectDefinition());
- gotException = true;
+ result = MenuResult.quit();
} else {
- managedObject = child;
+ result = MenuResult.<ManagedObject<?>>success(child);
}
} catch (DefinitionDecodingException e) {
dde = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ManagedObjectDecodingException e) {
mode = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (AuthorizationException e) {
authze = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ManagedObjectNotFoundException e) {
monfe = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ConcurrentModificationException e) {
cme = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (CommunicationException e) {
ce = e;
- gotException = true;
+ result = MenuResult.quit();
}
}
}
@@ -192,37 +207,37 @@
void appendManagedObjectPathElement(
OptionalRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
- if (!gotException) {
+ if (result.isSuccess()) {
try {
- ManagedObject<?> child = managedObject.getChild(r);
+ ManagedObject<?> child = result.getValue().getChild(r);
// Check that child is a sub-type of the specified
// definition.
if (!child.getManagedObjectDefinition().isChildOf(d)) {
- ae = ArgumentExceptionFactory.wrongManagedObjectType(r, child
+ clie = ArgumentExceptionFactory.wrongManagedObjectType(r, child
.getManagedObjectDefinition());
- gotException = true;
+ result = MenuResult.quit();
} else {
- managedObject = child;
+ result = MenuResult.<ManagedObject<?>>success(child);
}
} catch (DefinitionDecodingException e) {
dde = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ManagedObjectDecodingException e) {
mode = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (AuthorizationException e) {
authze = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ManagedObjectNotFoundException e) {
monfe = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ConcurrentModificationException e) {
cme = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (CommunicationException e) {
ce = e;
- gotException = true;
+ result = MenuResult.quit();
}
}
}
@@ -236,37 +251,37 @@
void appendManagedObjectPathElement(
SingletonRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
- if (!gotException) {
+ if (result.isSuccess()) {
try {
- ManagedObject<?> child = managedObject.getChild(r);
+ ManagedObject<?> child = result.getValue().getChild(r);
// Check that child is a sub-type of the specified
// definition.
if (!child.getManagedObjectDefinition().isChildOf(d)) {
- ae = ArgumentExceptionFactory.wrongManagedObjectType(r, child
+ clie = ArgumentExceptionFactory.wrongManagedObjectType(r, child
.getManagedObjectDefinition());
- gotException = true;
+ result = MenuResult.quit();
} else {
- managedObject = child;
+ result = MenuResult.<ManagedObject<?>>success(child);
}
} catch (DefinitionDecodingException e) {
dde = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ManagedObjectDecodingException e) {
mode = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (AuthorizationException e) {
authze = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ManagedObjectNotFoundException e) {
monfe = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (ConcurrentModificationException e) {
cme = e;
- gotException = true;
+ result = MenuResult.quit();
} catch (CommunicationException e) {
ce = e;
- gotException = true;
+ result = MenuResult.quit();
}
}
}
@@ -276,14 +291,20 @@
/**
* Finds the named managed object.
*
+ * @param app
+ * The console application.
* @param context
* The management context.
* @param path
* The managed object path.
* @param args
* The managed object path arguments.
- * @return Returns the named managed object.
- * @throws ArgumentException
+ * @return Returns a {@link MenuResult#success()} containing the
+ * managed object referenced by the provided managed
+ * object path, or {@link MenuResult#quit()}, or
+ * {@link MenuResult#cancel()}, if the sub-command was
+ * run interactively and the user chose to quit or cancel.
+ * @throws CLIException
* If one of the naming arguments referenced a managed
* object of the wrong type.
* @throws DefinitionDecodingException
@@ -306,18 +327,19 @@
* If the client cannot contact the server due to an
* underlying communication problem.
*/
- public ManagedObject<?> find(ManagementContext context,
- ManagedObjectPath<?, ?> path, List<String> args)
- throws ArgumentException, CommunicationException,
+ public MenuResult<ManagedObject<?>> find(ConsoleApplication app,
+ ManagementContext context, ManagedObjectPath<?, ?> path,
+ List<String> args) throws CLIException, CommunicationException,
AuthorizationException, ConcurrentModificationException,
DefinitionDecodingException, ManagedObjectDecodingException,
ManagedObjectNotFoundException {
- this.managedObject = context.getRootConfigurationManagedObject();
+ this.result = MenuResult.<ManagedObject<?>> success(context
+ .getRootConfigurationManagedObject());
+ this.app = app;
this.args = args;
this.argIndex = 0;
- this.gotException = false;
- this.ae = null;
+ this.clie = null;
this.authze = null;
this.ce = null;
this.cme = null;
@@ -327,8 +349,10 @@
path.serialize(this);
- if (ae != null) {
- throw ae;
+ if (result.isSuccess()) {
+ return result;
+ } else if (clie != null) {
+ throw clie;
} else if (authze != null) {
throw authze;
} else if (ce != null) {
@@ -342,7 +366,8 @@
} else if (monfe != null) {
throw monfe;
} else {
- return managedObject;
+ // User requested termination interactively.
+ return result;
}
}
}
@@ -500,6 +525,12 @@
}
/**
+ * The threshold above which choice menus should be displayed in
+ * multiple columns.
+ */
+ public static final int MULTI_COLUMN_THRESHOLD = 8;
+
+ /**
* The value for the long option advanced.
*/
private static final String OPTION_DSCFG_LONG_ADVANCED = "advanced";
@@ -552,9 +583,6 @@
// 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;
@@ -575,12 +603,41 @@
/**
* Create a new sub-command handler.
- *
- * @param app
- * The application instance.
*/
- protected SubCommandHandler(ConsoleApplication app) {
- this.app = app;
+ protected SubCommandHandler() {
+ // No implementation required.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public final int compareTo(SubCommandHandler o) {
+ String s1 = getSubCommand().getName();
+ String s2 = o.getSubCommand().getName();
+
+ return s1.compareTo(s2);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (obj instanceof SubCommandHandler) {
+ SubCommandHandler other = (SubCommandHandler) obj;
+
+ String s1 = getSubCommand().getName();
+ String s2 = other.getSubCommand().getName();
+ return s1.equals(s2);
+ } else {
+ return false;
+ }
}
@@ -607,17 +664,38 @@
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int hashCode() {
+ return getSubCommand().getName().hashCode();
+ }
+
+
+
+ /**
* Run this sub-command handler.
*
- * @return Returns zero if the sub-command completed successfully or
- * non-zero if it did not.
+ * @param app
+ * The console application.
+ * @param factory
+ * The management context factory.
+ * @return Returns a {@link MenuResult#success()} containing zero if
+ * the sub-command completed successfully or non-zero if it
+ * did not, or {@link MenuResult#quit()}, or
+ * {@link MenuResult#cancel()}, if the sub-command was run
+ * interactively and the user chose to quit or cancel.
* @throws ArgumentException
* If an argument required by the sub-command could not be
* parsed successfully.
* @throws ClientException
* If the management context could not be created.
+ * @throws CLIException
+ * If a CLI exception occurred.
*/
- public abstract int run() throws ArgumentException, ClientException;
+ public abstract MenuResult<Integer> run(ConsoleApplication app,
+ ManagementContextFactory factory) throws ArgumentException,
+ ClientException, CLIException;
@@ -702,26 +780,22 @@
/**
- * 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 app
+ * The console application.
+ * @param context
+ * The management context.
* @param path
* The managed object path.
* @param args
* The list of managed object names required by the path.
- * @return Returns the managed object referenced by the provided
- * managed object path.
+ * @return Returns a {@link MenuResult#success()} containing the
+ * managed object referenced by the provided managed object
+ * path, or {@link MenuResult#quit()}, or
+ * {@link MenuResult#cancel()}, if the sub-command was run
+ * interactively and the user chose to quit or cancel.
* @throws DefinitionDecodingException
* If the managed object was found but its type could not
* be determined.
@@ -741,20 +815,21 @@
* @throws CommunicationException
* If the client cannot contact the server due to an
* underlying communication problem.
- * @throws ArgumentException
+ * @throws CLIException
* 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(
- ManagedObjectPath<?, ?> path, List<String> args)
- throws ArgumentException, AuthorizationException,
- DefinitionDecodingException, ManagedObjectDecodingException,
- CommunicationException, ConcurrentModificationException,
- ManagedObjectNotFoundException, ClientException {
+ protected final MenuResult<ManagedObject<?>> getManagedObject(
+ ConsoleApplication app, ManagementContext context,
+ ManagedObjectPath<?, ?> path, List<String> args) throws CLIException,
+ AuthorizationException, DefinitionDecodingException,
+ ManagedObjectDecodingException, CommunicationException,
+ ConcurrentModificationException, ManagedObjectNotFoundException,
+ ClientException {
ManagedObjectFinder finder = new ManagedObjectFinder();
- return finder.find(app.getManagementContext(), path, args);
+ return finder.find(app, context, path, args);
}
@@ -762,6 +837,8 @@
/**
* Gets the values of the naming arguments.
*
+ * @param app
+ * The console application.
* @param namingArgs
* The naming arguments.
* @return Returns the values of the naming arguments.
@@ -769,7 +846,7 @@
* If one of the naming arguments is missing and the
* application is non-interactive.
*/
- protected final List<String> getNamingArgValues(
+ protected final List<String> getNamingArgValues(ConsoleApplication app,
List<StringArgument> namingArgs) throws ArgumentException {
ArrayList<String> values = new ArrayList<String>(namingArgs.size());
for (StringArgument arg : namingArgs) {
@@ -902,14 +979,19 @@
* The type of child client configuration.
* @param <S>
* The type of child server configuration.
+ * @param app
+ * The console application.
* @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.
+ * @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
@@ -917,52 +999,62 @@
* @throws AuthorizationException
* If the children cannot be listed due to an
* authorization failure.
- * @throws ArgumentException
+ * @throws CLIException
* 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,
+ MenuResult<String> readChildName(
+ ConsoleApplication app, ManagedObject<?> parent,
InstantiableRelationDefinition<C, S> r,
AbstractManagedObjectDefinition<? extends C, ? extends S> d)
throws AuthorizationException, ConcurrentModificationException,
- CommunicationException, ArgumentException {
+ CommunicationException, CLIException {
if (d == null) {
d = r.getChildDefinition();
}
+ app.println();
+ app.println();
String[] children = parent.listChildren(r, d);
switch (children.length) {
case 0: {
// No options available - abort.
Message msg =
ERR_DSCFG_ERROR_FINDER_NO_CHILDREN.get(d.getUserFriendlyPluralName());
- throw new ArgumentException(msg);
+ throw new CLIException(msg);
}
case 1: {
// Only one option available so confirm that the user wishes to
// access it.
Message msg = INFO_DSCFG_FINDER_PROMPT_SINGLE.get(
d.getUserFriendlyName(), children[0]);
- if (getConsoleApplication().confirmAction(msg)) {
- return children[0];
+ if (app.confirmAction(msg, true)) {
+ return MenuResult.success(children[0]);
} else {
- msg = ERR_DSCFG_ERROR_FINDER_SINGLE_CHILD_REJECTED.get(
- d.getUserFriendlyName());
- throw new ArgumentException(msg);
+ return MenuResult.cancel();
}
}
default: {
// Display a menu.
+ MenuBuilder<String> builder = new MenuBuilder<String>(app);
+ builder.setMultipleColumnThreshold(MULTI_COLUMN_THRESHOLD);
+ builder.setPrompt(INFO_DSCFG_FINDER_PROMPT_MANY.get(d
+ .getUserFriendlyName()));
+
Arrays.sort(children, String.CASE_INSENSITIVE_ORDER);
- ArrayList<Message> desc = new ArrayList<Message>();
- for (String s : Arrays.asList(children)) {
- desc.add(Message.raw(s));
+ for (String child : children) {
+ Message option = Message.raw("%s", child);
+ builder.addNumberedOption(option, MenuResult.success(child));
}
- Message prompt = INFO_DSCFG_FINDER_PROMPT_MANY.get(
- d.getUserFriendlyName());
- return getConsoleApplication().readChoice(
- prompt, desc, Arrays.asList(children), null);
+
+ if (app.isMenuDrivenMode()) {
+ builder.addCancelOption(true);
+ }
+ builder.addQuitOption();
+
+ Menu<String> menu = builder.toMenu();
+ return menu.run();
}
}
}
@@ -1062,4 +1154,7 @@
subCommand.addArgument(unitTimeArgument);
}
+
+
+
}
--
Gitblit v1.10.0