From 13a63611d24de8c5727e62a215b26354c1a22278 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Wed, 19 Mar 2008 18:09:56 +0000
Subject: [PATCH] Fix for issue 2197 (dsconfig: interactive mode should display the effective dsconfig command)
---
opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java | 308 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 298 insertions(+), 10 deletions(-)
diff --git a/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java b/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
index 8b32da6..8643ac7 100644
--- a/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
+++ b/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
@@ -80,6 +80,7 @@
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
import org.opends.server.tools.ToolConstants;
+import org.opends.server.util.args.Argument;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.StringArgument;
import org.opends.server.util.args.SubCommand;
@@ -356,6 +357,16 @@
private static final Character OPTION_DSCFG_SHORT_TYPE = 't';
+ /**
+ * The value for the long option remove (this is used only internally).
+ */
+ private static final String OPTION_DSCFG_LONG_REMOVE = "remove";
+
+ /**
+ * The value for the long option reset (this is used only internally).
+ */
+ private static final String OPTION_DSCFG_LONG_RESET = "reset";
+
/**
* Creates a new create-xxx sub-command for an instantiable
@@ -410,7 +421,6 @@
}
-
/**
* Interactively lets a user create a new managed object beneath a
* parent.
@@ -445,6 +455,46 @@
ConsoleApplication app, ManagementContext context,
ManagedObject<?> parent, InstantiableRelationDefinition<C, S> rd)
throws ClientException, CLIException {
+ return createManagedObject(app, context, parent, rd, null);
+ }
+
+ /**
+ * Interactively lets a user create a new managed object beneath a
+ * parent.
+ *
+ * @param <C>
+ * The type of managed object which can be created.
+ * @param <S>
+ * The type of server managed object which can be created.
+ * @param app
+ * The console application.
+ * @param context
+ * The management context.
+ * @param parent
+ * The parent managed object.
+ * @param rd
+ * The relation beneath which the child managed object
+ * should be created.
+ * @param handler
+ * The subcommand handler whose command builder must be updated.
+ * @return Returns a MenuResult.success() containing the name of the
+ * created managed object if it was created successfully, or
+ * MenuResult.quit(), or MenuResult.cancel(), if the managed
+ * object was edited interactively and the user chose to
+ * quit or cancel.
+ * @throws ClientException
+ * If an unrecoverable client exception occurred whilst
+ * interacting with the server.
+ * @throws CLIException
+ * If an error occurred whilst interacting with the
+ * console.
+ */
+ private static <C extends ConfigurationClient, S extends Configuration>
+ MenuResult<String> createManagedObject(
+ ConsoleApplication app, ManagementContext context,
+ ManagedObject<?> parent, InstantiableRelationDefinition<C, S> rd,
+ SubCommandHandler handler)
+ throws ClientException, CLIException {
AbstractManagedObjectDefinition<C, S> d = rd.getChildDefinition();
// First determine what type of component the user wants to create.
@@ -470,7 +520,7 @@
createChildInteractively(app, parent, rd, mod, exceptions);
// Let the user interactively configure the managed object and commit it.
- MenuResult<Void> result2 = commitManagedObject(app, context, mo);
+ MenuResult<Void> result2 = commitManagedObject(app, context, mo, handler);
if (result2.isCancel()) {
return MenuResult.cancel();
} else if (result2.isQuit()) {
@@ -485,7 +535,8 @@
// Check that any referenced components are enabled if
// required.
private static MenuResult<Void> checkReferences(ConsoleApplication app,
- ManagementContext context, ManagedObject<?> mo) throws ClientException,
+ ManagementContext context, ManagedObject<?> mo,
+ SubCommandHandler handler) throws ClientException,
CLIException {
ManagedObjectDefinition<?, ?> d = mo.getManagedObjectDefinition();
Message ufn = d.getUserFriendlyName();
@@ -549,7 +600,7 @@
if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn),
true)) {
MenuResult<Void> result = SetPropSubCommandHandler
- .modifyManagedObject(app, context, ref);
+ .modifyManagedObject(app, context, ref, handler);
if (result.isQuit()) {
return result;
} else if (result.isSuccess()) {
@@ -570,7 +621,7 @@
if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn),
true)) {
MenuResult<Void> result = SetPropSubCommandHandler
- .modifyManagedObject(app, context, ref);
+ .modifyManagedObject(app, context, ref, handler);
if (result.isQuit()) {
return result;
} else if (result.isSuccess()) {
@@ -589,7 +640,7 @@
if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT_TO_ENABLE.get(
rufn, name, ufn), true)) {
MenuResult<Void> result = SetPropSubCommandHandler
- .modifyManagedObject(app, context, ref);
+ .modifyManagedObject(app, context, ref, handler);
if (result.isQuit()) {
return result;
} else if (result.isSuccess()) {
@@ -634,12 +685,14 @@
// Commit a new managed object's configuration.
private static MenuResult<Void> commitManagedObject(ConsoleApplication app,
- ManagementContext context, ManagedObject<?> mo) throws ClientException,
+ ManagementContext context, ManagedObject<?> mo, SubCommandHandler handler)
+ throws ClientException,
CLIException {
ManagedObjectDefinition<?, ?> d = mo.getManagedObjectDefinition();
Message ufn = d.getUserFriendlyName();
while (true) {
+ PropertyValueEditor editor = new PropertyValueEditor(app, context);
// Interactively set properties if applicable.
if (app.isInteractive()) {
SortedSet<PropertyDefinition<?>> properties =
@@ -654,12 +707,11 @@
properties.add(pd);
}
- PropertyValueEditor editor = new PropertyValueEditor(app, context);
MenuResult<Void> result = editor.edit(mo, properties, false);
// Interactively enable/edit referenced components.
if (result.isSuccess()) {
- result = checkReferences(app, context, mo);
+ result = checkReferences(app, context, mo, handler);
if (result.isAgain()) {
// Edit again.
continue;
@@ -687,6 +739,22 @@
Message msg = INFO_DSCFG_CONFIRM_CREATE_SUCCESS.get(ufn);
app.printVerboseMessage(msg);
+ for (PropertyEditorModification mod : editor.getModifications())
+ {
+ try
+ {
+ Argument arg = createArgument(mod);
+ handler.getCommandBuilder().addArgument(arg);
+ }
+ catch (ArgumentException ae)
+ {
+ // This is a bug
+ throw new RuntimeException(
+ "Unexpected error generating the command builder: "+ae, ae);
+ }
+ }
+ handler.setCommandBuilderUseful(true);
+
return MenuResult.success();
} catch (MissingMandatoryPropertiesException e) {
if (app.isInteractive()) {
@@ -984,6 +1052,8 @@
+
+
// Common constructor.
private CreateSubCommandHandler(
SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
@@ -1128,6 +1198,14 @@
// Get the naming argument values.
List<String> names = getNamingArgValues(app, namingArgs);
+ // Reset the command builder
+ getCommandBuilder().clearArguments();
+
+ setCommandBuilderUseful(false);
+
+ // Update the command builder.
+ updateCommandBuilderWithSubCommand();
+
// Encode the provided properties.
List<String> propertyArgs = propertySetArgument.getValues();
MyPropertyProvider provider = new MyPropertyProvider(d,
@@ -1178,6 +1256,8 @@
ManagedObject<? extends C> child;
List<DefaultBehaviorException> exceptions =
new LinkedList<DefaultBehaviorException>();
+ boolean isNameProvidedInteractively = false;
+ String providedNamingArgName = null;
if (relation instanceof InstantiableRelationDefinition) {
InstantiableRelationDefinition<C, S> irelation =
(InstantiableRelationDefinition<C, S>) relation;
@@ -1188,6 +1268,9 @@
app.println();
child = createChildInteractively(app, parent, irelation,
d, exceptions);
+ isNameProvidedInteractively = true;
+ providedNamingArgName =
+ CLIProfile.getInstance().getNamingArgument(irelation);
} else {
throw ArgumentExceptionFactory
.missingMandatoryNonInteractiveArgument(namingArgs.get(names
@@ -1219,12 +1302,132 @@
// Now the command line changes have been made, create the managed
// object interacting with the user to fix any problems if
// required.
- MenuResult<Void> result2 = commitManagedObject(app, context, child);
+ MenuResult<Void> result2 = commitManagedObject(app, context, child, this);
if (result2.isCancel()) {
return MenuResult.cancel();
} else if (result2.isQuit()) {
return MenuResult.quit();
} else {
+ if (typeArgument.hasValue())
+ {
+ getCommandBuilder().addArgument(typeArgument);
+ }
+ else
+ {
+ // Set the type provided by the user
+ StringArgument arg = new StringArgument(typeArgument.getName(),
+ OPTION_DSCFG_SHORT_TYPE,
+ OPTION_DSCFG_LONG_TYPE, false, false, true,
+ INFO_TYPE_PLACEHOLDER.get(), typeArgument.getDefaultValue(),
+ typeArgument.getPropertyName(),
+ typeArgument.getDescription());
+ arg.addValue(getTypeName(d));
+ getCommandBuilder().addArgument(arg);
+ }
+ if (propertySetArgument.hasValue())
+ {
+ /*
+ We might have some conflicts in terms of arguments: the user might
+ have provided some values that were not good and then these have
+ overwritten when asking for them interactively: filter them */
+ StringArgument filteredArg = new StringArgument(OPTION_DSCFG_LONG_SET,
+ OPTION_DSCFG_SHORT_SET, OPTION_DSCFG_LONG_SET, false, true, true,
+ INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
+ INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
+ for (String value : propertySetArgument.getValues())
+ {
+ boolean addValue = true;
+ int index = value.indexOf(':');
+ if (index != -1)
+ {
+ String propName = value.substring(0, index);
+ for (Argument arg : getCommandBuilder().getArguments())
+ {
+ for (String value2 : arg.getValues())
+ {
+ String prop2Name;
+ if (arg.getName().equals(OPTION_DSCFG_LONG_SET) ||
+ arg.getName().equals(OPTION_DSCFG_LONG_REMOVE))
+ {
+ int index2 = value2.indexOf(':');
+ if (index2 != -1)
+ {
+ prop2Name = value2.substring(0, index2);
+ }
+ else
+ {
+ prop2Name = null;
+ }
+ }
+ else if (arg.getName().equals(OPTION_DSCFG_LONG_RESET))
+ {
+ prop2Name = value2;
+ }
+ else
+ {
+ prop2Name = null;
+ }
+ if (prop2Name != null)
+ {
+ if (prop2Name.equalsIgnoreCase(propName))
+ {
+ addValue = false;
+ break;
+ }
+ }
+ }
+ if (!addValue)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ addValue = false;
+ }
+ if (addValue)
+ {
+ filteredArg.addValue(value);
+ }
+ }
+ if (filteredArg.hasValue())
+ {
+ getCommandBuilder().addArgument(filteredArg);
+ }
+ }
+
+ /* Filter the arguments that are used internally */
+ List<Argument> argsCopy = new LinkedList<Argument>(
+ getCommandBuilder().getArguments());
+ for (Argument arg : argsCopy)
+ {
+ if (arg.getName().equals(OPTION_DSCFG_LONG_RESET) ||
+ arg.getName().equals(OPTION_DSCFG_LONG_REMOVE))
+ {
+ getCommandBuilder().removeArgument(arg);
+ }
+ }
+
+ if (isNameProvidedInteractively)
+ {
+ StringArgument arg = new StringArgument(providedNamingArgName, null,
+ providedNamingArgName, false, true,
+ INFO_NAME_PLACEHOLDER.get(),
+ INFO_DSCFG_DESCRIPTION_NAME_CREATE.get(d.getUserFriendlyName()));
+ arg.addValue(child.getManagedObjectPath().getName());
+ getCommandBuilder().addArgument(arg);
+ }
+ else
+ {
+ for (StringArgument arg : namingArgs)
+ {
+ if (arg.isPresent())
+ {
+ getCommandBuilder().addArgument(arg);
+ }
+ }
+ }
return MenuResult.success(0);
}
}
@@ -1240,4 +1443,89 @@
// validated.
mo.setPropertyValues(pd, values);
}
+
+ /**
+ * Creates an argument (the one that the user should provide in the
+ * command-line) that is equivalent to the modification proposed by the user
+ * in the provided PropertyEditorModification object.
+ * @param mod the object describing the modification made.
+ * @return the argument representing the modification.
+ * @throws ArgumentException if there is a problem creating the argument.
+ */
+ private static Argument createArgument(PropertyEditorModification mod)
+ throws ArgumentException
+ {
+ StringArgument arg;
+
+ String propName = mod.getPropertyDefinition().getName();
+
+ switch (mod.getType())
+ {
+ case ADD:
+ arg = new StringArgument(OPTION_DSCFG_LONG_SET,
+ OPTION_DSCFG_SHORT_SET, OPTION_DSCFG_LONG_SET, false, true, true,
+ INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
+ INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
+ for (Object value : mod.getModificationValues())
+ {
+ arg.addValue(propName+':'+value);
+ }
+ break;
+ case SET:
+ arg = new StringArgument(OPTION_DSCFG_LONG_SET,
+ OPTION_DSCFG_SHORT_SET, OPTION_DSCFG_LONG_SET, false, true, true,
+ INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
+ INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
+ for (Object value : mod.getModificationValues())
+ {
+ arg.addValue(propName+':'+value);
+ }
+ break;
+ case RESET:
+ arg = new StringArgument(OPTION_DSCFG_LONG_RESET,
+ null, OPTION_DSCFG_LONG_RESET, false, true, true,
+ INFO_PROPERTY_PLACEHOLDER.get(), null, null,
+ INFO_DSCFG_DESCRIPTION_RESET_PROP.get());
+ arg.addValue(propName);
+ break;
+ case REMOVE:
+ arg = new StringArgument(OPTION_DSCFG_LONG_REMOVE,
+ null, OPTION_DSCFG_LONG_REMOVE, false, true,
+ true, INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
+ INFO_DSCFG_DESCRIPTION_REMOVE_PROP_VAL.get());
+ for (Object value : mod.getModificationValues())
+ {
+ arg.addValue(propName+':'+value);
+ }
+ arg = null;
+ break;
+ default:
+ // Bug
+ throw new IllegalStateException("Unknown modification type: "+
+ mod.getType());
+ }
+ return arg;
+ }
+
+ /**
+ * Returns the type name for a given ManagedObjectDefinition.
+ * @param d the ManagedObjectDefinition.
+ * @return the type name for the provided ManagedObjectDefinition.
+ */
+ private String getTypeName(
+ ManagedObjectDefinition<? extends C, ? extends S> d)
+ {
+ String name = d.getName();
+ for (String key : types.keySet())
+ {
+ ManagedObjectDefinition<? extends C, ? extends S> current =
+ types.get(key);
+ if (current.equals(d))
+ {
+ name = key;
+ break;
+ }
+ }
+ return name;
+ }
}
--
Gitblit v1.10.0