opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java
@@ -23,13 +23,11 @@ * * * Copyright 2007-2010 Sun Microsystems, Inc. * Portions Copyright 2011 ForgeRock AS * Portions Copyright 2011-2013 ForgeRock AS * Portions Copyright 2012 profiq, s.r.o. */ package org.opends.server.tools.dsconfig; import static org.opends.messages.DSConfigMessages.*; import static org.opends.messages.ToolMessages.*; import static org.opends.server.tools.dsconfig.ArgumentExceptionFactory.*; @@ -80,7 +78,7 @@ import org.opends.server.util.cli.ConsoleApplication; import org.opends.server.util.cli.MenuResult; import com.forgerock.opendj.util.Pair; /** * A sub-command handler which is used to modify the properties of a @@ -382,8 +380,9 @@ // Check that any referenced components are enabled if // required. /** * Check that any referenced components are enabled if required. */ private static MenuResult<Void> checkReferences(ConsoleApplication app, ManagementContext context, ManagedObject<?> mo, SubCommandHandler handler) throws ClientException, @@ -586,34 +585,42 @@ // The sub-commands naming arguments. /** The sub-commands naming arguments. */ private final List<StringArgument> namingArgs; // The path of the managed object. /** The path of the managed object. */ private final ManagedObjectPath<?, ?> path; // The argument which should be used to specify zero or more // property value adds. /** * The argument which should be used to specify zero or more property value * adds. */ private final StringArgument propertyAddArgument; // The argument which should be used to specify zero or more // property value removes. /** * The argument which should be used to specify zero or more property value * removes. */ private final StringArgument propertyRemoveArgument; // The argument which should be used to specify zero or more // property value resets. /** * The argument which should be used to specify zero or more property value * resets. */ private final StringArgument propertyResetArgument; // The argument which should be used to specify zero or more // property value assignments. /** * The argument which should be used to specify zero or more property value * assignments. */ private final StringArgument propertySetArgument; // The sub-command associated with this handler. /** The sub-command associated with this handler. */ private final SubCommand subCommand; // Private constructor. /** Private constructor. */ private SetPropSubCommandHandler( SubCommandArgumentParser parser, ManagedObjectPath<?, ?> path, RelationDefinition<?, ?> r) throws ArgumentException { @@ -670,24 +677,21 @@ * @return Returns the relation definition associated with the type * of component that this sub-command handles. */ @Override public RelationDefinition<?, ?> getRelationDefinition() { return path.getRelationDefinition(); } /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public SubCommand getSubCommand() { return subCommand; } /** * {@inheritDoc} */ /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public MenuResult<Integer> run(ConsoleApplication app, @@ -775,22 +779,15 @@ OPTION_DSCFG_LONG_RESET); } // Check the property definition. PropertyDefinition<?> pd; try { pd = d.getPropertyDefinition(m); } catch (IllegalArgumentException e) { throw ArgumentExceptionFactory.unknownProperty(d, m); } PropertyDefinition<?> pd = getPropertyDefinition(d, m); // Mandatory properties which have no defined defaults cannot be // reset. if (pd.hasOption(PropertyOption.MANDATORY)) { if (pd.getDefaultBehaviorProvider() instanceof UndefinedDefaultBehaviorProvider) { throw ArgumentExceptionFactory.unableToResetMandatoryProperty(d, m, OPTION_DSCFG_LONG_SET); } // Mandatory properties which have no defined defaults cannot be reset. if (pd.hasOption(PropertyOption.MANDATORY) && pd.getDefaultBehaviorProvider() instanceof UndefinedDefaultBehaviorProvider) { throw ArgumentExceptionFactory.unableToResetMandatoryProperty(d, m, OPTION_DSCFG_LONG_SET); } // Save the modification type. @@ -802,30 +799,11 @@ // Set properties. for (String m : propertySetArgument.getValues()) { // Parse the property "property:value". int sep = m.indexOf(':'); Pair<String, String> pair = parseValue(m); String propertyName = pair.getFirst(); String value = pair.getSecond(); if (sep < 0) { throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m); } if (sep == 0) { throw ArgumentExceptionFactory.missingNameInPropertyArgument(m); } String propertyName = m.substring(0, sep); String value = m.substring(sep + 1, m.length()); if (value.length() == 0) { throw ArgumentExceptionFactory.missingValueInPropertyArgument(m); } // Check the property definition. PropertyDefinition<?> pd; try { pd = d.getPropertyDefinition(propertyName); } catch (IllegalArgumentException e) { throw ArgumentExceptionFactory.unknownProperty(d, propertyName); } PropertyDefinition<?> pd = getPropertyDefinition(d, propertyName); // Apply the modification. if (lastModTypes.containsKey(propertyName)) { @@ -838,34 +816,15 @@ // Remove properties. for (String m : propertyRemoveArgument.getValues()) { // Parse the property "property:value". int sep = m.indexOf(':'); Pair<String, String> pair = parseValue(m); String propertyName = pair.getFirst(); String value = pair.getSecond(); if (sep < 0) { throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m); } if (sep == 0) { throw ArgumentExceptionFactory.missingNameInPropertyArgument(m); } String propertyName = m.substring(0, sep); String value = m.substring(sep + 1, m.length()); if (value.length() == 0) { throw ArgumentExceptionFactory.missingValueInPropertyArgument(m); } // Check the property definition. PropertyDefinition<?> pd; try { pd = d.getPropertyDefinition(propertyName); } catch (IllegalArgumentException e) { throw ArgumentExceptionFactory.unknownProperty(d, propertyName); } PropertyDefinition<?> pd = getPropertyDefinition(d, propertyName); // Apply the modification. if (lastModTypes.containsKey(propertyName) && (lastModTypes.get(propertyName) == ModificationType.SET)) { if (lastModTypes.containsKey(propertyName) && lastModTypes.get(propertyName) == ModificationType.SET) { throw ArgumentExceptionFactory.incompatiblePropertyModification(m); } @@ -875,34 +834,15 @@ // Add properties. for (String m : propertyAddArgument.getValues()) { // Parse the property "property:value". int sep = m.indexOf(':'); Pair<String, String> pair = parseValue(m); String propertyName = pair.getFirst(); String value = pair.getSecond(); if (sep < 0) { throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m); } if (sep == 0) { throw ArgumentExceptionFactory.missingNameInPropertyArgument(m); } String propertyName = m.substring(0, sep); String value = m.substring(sep + 1, m.length()); if (value.length() == 0) { throw ArgumentExceptionFactory.missingValueInPropertyArgument(m); } // Check the property definition. PropertyDefinition<?> pd; try { pd = d.getPropertyDefinition(propertyName); } catch (IllegalArgumentException e) { throw ArgumentExceptionFactory.unknownProperty(d, propertyName); } PropertyDefinition<?> pd = getPropertyDefinition(d, propertyName); // Apply the modification. if (lastModTypes.containsKey(propertyName) && (lastModTypes.get(propertyName) == ModificationType.SET)) { if (lastModTypes.containsKey(propertyName) && lastModTypes.get(propertyName) == ModificationType.SET) { throw ArgumentExceptionFactory.incompatiblePropertyModification(m); } @@ -948,8 +888,38 @@ } } /** Parse and check the property "property:value". */ private Pair<String, String> parseValue(String m) throws ArgumentException { int sep = m.indexOf(':'); if (sep < 0) { throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m); } if (sep == 0) { throw ArgumentExceptionFactory.missingNameInPropertyArgument(m); } // Apply a single modification to the current change-set. String propertyName = m.substring(0, sep); String value = m.substring(sep + 1, m.length()); if (value.length() == 0) { throw ArgumentExceptionFactory.missingValueInPropertyArgument(m); } return Pair.of(propertyName, value); } /** Get and check the property definition. */ private PropertyDefinition<?> getPropertyDefinition( ManagedObjectDefinition<?, ?> def, String propertyName) throws ArgumentException { try { return def.getPropertyDefinition(propertyName); } catch (IllegalArgumentException e) { throw ArgumentExceptionFactory.unknownProperty(def, propertyName); } } /** Apply a single modification to the current change-set. */ @SuppressWarnings("unchecked") private <T> void modifyPropertyValues(ManagedObject<?> mo, PropertyDefinition<T> pd, Map<PropertyDefinition, Set> changes, @@ -976,7 +946,7 @@ values.add(value); break; case REMOVE: if (values.remove(value) != true) { if (!values.remove(value)) { // value was not part of values throw ArgumentExceptionFactory. unknownValueForMultiValuedProperty(s, pd.getName()); opends/src/server/org/opends/server/util/args/Argument.java
@@ -72,7 +72,7 @@ /** The unique ID of the description for this argument. */ private Message description; /** The set of values for this argument. */ /** The set of provided values for this argument. */ private LinkedList<String> values; /** The default value for the argument if none other is provided. */ @@ -89,7 +89,8 @@ /** * The value placeholder for this argument, which will be used in usage * information. * information. It describes the format that must be used to specify the * values for this argument. */ private Message valuePlaceholder; @@ -692,19 +693,11 @@ sb.append("--").append(longIdentifier); } } if (isRequired) { sb.append(", required"); } if (isMultiValued) { sb.append(", multiValued"); } if (needsValue) { sb.append(", needsValue"); } sb.append(", ").append(isRequired ? "required" : "optional"); sb.append(", ").append(isMultiValued ? "multiValued" : "singleValued"); sb.append(", defaultValue=\"").append(defaultValue) .append("\", valueFormat=\"").append(valuePlaceholder) .append("\", providedValues=\"").append(values) .append("\", description=\"").append(description) .append("\"]"); return sb.toString(); opends/src/server/org/opends/server/util/args/ArgumentParser.java
@@ -763,56 +763,6 @@ parseArguments(rawArguments, null); } /** * Parses the provided set of arguments and updates the information associated * with this parser accordingly. Default values for unspecified arguments * may be read from the specified properties file. * * @param rawArguments The set of raw arguments to parse. * @param propertiesFile The path to the properties file to use to * obtain default values for unspecified * properties. * @param requirePropertiesFile Indicates whether the parsing should fail if * the provided properties file does not exist * or is not accessible. * * @throws ArgumentException If a problem was encountered while parsing the * provided arguments or interacting with the * properties file. */ public void parseArguments(String[] rawArguments, String propertiesFile, boolean requirePropertiesFile) throws ArgumentException { this.rawArguments = rawArguments; Properties argumentProperties = null; try { Properties p = new Properties(); FileInputStream fis = new FileInputStream(propertiesFile); p.load(fis); fis.close(); argumentProperties = p; } catch (Exception e) { if (requirePropertiesFile) { Message message = ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE.get( String.valueOf(propertiesFile), getExceptionMessage(e)); throw new ArgumentException(message, e); } } parseArguments(rawArguments, argumentProperties); } /** * Parses the provided set of arguments and updates the information associated * with this parser accordingly. Default values for unspecified arguments may @@ -1362,10 +1312,7 @@ { return f.getAbsolutePath(); } else { return null; } return null; } /** @@ -1538,12 +1485,10 @@ * The buffer to which the usage information should be * appended. */ private void printArgumentUsage(Argument a, StringBuilder buffer) private void printArgumentUsage(Argument a, StringBuilder buffer) { // Write a line with the short and/or long identifiers that may be // used // for the argument. final int indentLength = INDENT.length(); // Write a line with the short and/or long identifiers that may be // used for the argument. Character shortID = a.getShortIdentifier(); String longID = a.getLongIdentifier(); if (shortID != null) @@ -1609,50 +1554,59 @@ } // Write one or more lines with the description of the argument. // We will // indent the description five characters and try our best to wrap // at or // before column 79 so it will be friendly to 80-column displays. Message description = a.getDescription(); int descMaxLength = MAX_LENGTH - indentLength - 1; if (description.length() <= descMaxLength) indentAndWrap(INDENT, a.getDescription(), buffer); if (a.needsValue() && a.getDefaultValue() != null && a.getDefaultValue().length() > 0) { buffer.append(INDENT); buffer.append(description); indentAndWrap(INDENT, INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get(a .getDefaultValue()), buffer); } } /** * Write one or more lines with the description of the argument. We will * indent the description five characters and try our best to wrap at or * before column 79 so it will be friendly to 80-column displays. */ private void indentAndWrap(String indent, Message text, StringBuilder buffer) { int actualSize = MAX_LENGTH - indent.length() - 1; if (text.length() <= actualSize) { buffer.append(indent); buffer.append(text); buffer.append(EOL); } else { String s = description.toString(); while (s.length() > descMaxLength) String s = text.toString(); while (s.length() > actualSize) { int spacePos = s.lastIndexOf(' ', descMaxLength); int spacePos = s.lastIndexOf(' ', actualSize); if (spacePos > 0) { buffer.append(INDENT); buffer.append(indent); buffer.append(s.substring(0, spacePos).trim()); s = s.substring(spacePos+1).trim(); s = s.substring(spacePos + 1).trim(); buffer.append(EOL); } else { // There are no spaces in the first 74 columns. See if there // is one // after that point. If so, then break there. If not, then // don't // break at all. // There are no spaces in the first 74 columns. // See if there is one after that point. // If so, then break there. If not, then don't break at all. spacePos = s.indexOf(' '); if (spacePos > 0) { buffer.append(INDENT); buffer.append(indent); buffer.append(s.substring(0, spacePos).trim()); s = s.substring(spacePos+1).trim(); s = s.substring(spacePos + 1).trim(); buffer.append(EOL); } else { buffer.append(INDENT); buffer.append(indent); buffer.append(s); s = ""; buffer.append(EOL); @@ -1662,21 +1616,11 @@ if (s.length() > 0) { buffer.append(INDENT); buffer.append(indent); buffer.append(s); buffer.append(EOL); } } if (a.needsValue() && a.getDefaultValue() != null && a.getDefaultValue().length() > 0) { buffer.append(INDENT); buffer.append(INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get( a.getDefaultValue()).toString()); buffer.append(EOL); } } /** @@ -1687,17 +1631,14 @@ * @return argument group appropriate for <code>argument</code> */ protected ArgumentGroup getStandardGroup(Argument argument) { ArgumentGroup group; if (isInputOutputArgument(argument)) { group = ioArgGroup; return ioArgGroup; } else if (isGeneralArgument(argument)) { group = generalArgGroup; return generalArgGroup; } else if (isLdapConnectionArgument(argument)) { group = ldapArgGroup; } else { group = defaultArgGroup; return ldapArgGroup; } return group; return defaultArgGroup; } /** @@ -1740,10 +1681,9 @@ private boolean isInputOutputArgument(Argument arg) { boolean io = false; if (arg != null) { String longId = arg.getLongIdentifier(); io = OPTION_LONG_VERBOSE.equals(longId) || return OPTION_LONG_VERBOSE.equals(longId) || OPTION_LONG_QUIET.equals(longId) || OPTION_LONG_NO_PROMPT.equals(longId) || OPTION_LONG_PROP_FILE_PATH.equals(longId) || @@ -1755,14 +1695,13 @@ OPTION_LONG_EQUIVALENT_COMMAND_FILE_PATH.equals(longId) || OPTION_LONG_BATCH_FILE_PATH.equals(longId); } return io; return false; } private boolean isLdapConnectionArgument(Argument arg) { boolean ldap = false; if (arg != null) { String longId = arg.getLongIdentifier(); ldap = OPTION_LONG_USE_SSL.equals(longId) || return OPTION_LONG_USE_SSL.equals(longId) || OPTION_LONG_START_TLS.equals(longId) || OPTION_LONG_HOST.equals(longId) || OPTION_LONG_PORT.equals(longId) || @@ -1788,18 +1727,17 @@ OPTION_LONG_PROTOCOL_VERSION.equals(longId) || OPTION_LONG_CONNECT_TIMEOUT.equals(longId); } return ldap; return false; } private boolean isGeneralArgument(Argument arg) { boolean general = false; if (arg != null) { String longId = arg.getLongIdentifier(); general = OPTION_LONG_HELP.equals(longId) || OPTION_LONG_PRODUCT_VERSION.equals(longId); return OPTION_LONG_HELP.equals(longId) || OPTION_LONG_PRODUCT_VERSION.equals(longId); } return general; return false; } /** @@ -1810,12 +1748,7 @@ */ public boolean isUsageArgumentPresent() { boolean isUsageArgumentPresent = false; if (usageArgument != null) { isUsageArgumentPresent = usageArgument.isPresent(); } return isUsageArgumentPresent; return usageArgument != null && usageArgument.isPresent(); } /** @@ -1845,21 +1778,14 @@ public static String getBindPassword(StringArgument clearArg, FileBasedArgument fileArg) { String pwd; if (clearArg.isPresent()) { pwd = clearArg.getValue(); return clearArg.getValue(); } else if (fileArg.isPresent()) else if (fileArg.isPresent()) { pwd = fileArg.getValue(); return fileArg.getValue(); } else { pwd = null; } return pwd; return null; } } opends/src/server/org/opends/server/util/args/SubCommandArgumentParser.java
@@ -27,7 +27,6 @@ */ package org.opends.server.util.args; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.util.*; @@ -672,57 +671,6 @@ parseArguments(rawArguments, null); } /** * Parses the provided set of arguments and updates the information associated * with this parser accordingly. Default values for unspecified arguments * may be read from the specified properties file. * * @param rawArguments The set of raw arguments to parse. * @param propertiesFile The path to the properties file to use to * obtain default values for unspecified * properties. * @param requirePropertiesFile Indicates whether the parsing should fail if * the provided properties file does not exist * or is not accessible. * * @throws ArgumentException If a problem was encountered while parsing the * provided arguments or interacting with the * properties file. */ @Override public void parseArguments(String[] rawArguments, String propertiesFile, boolean requirePropertiesFile) throws ArgumentException { this.rawArguments = rawArguments; Properties argumentProperties = null; try { Properties p = new Properties(); FileInputStream fis = new FileInputStream(propertiesFile); p.load(fis); fis.close(); argumentProperties = p; } catch (Exception e) { if (requirePropertiesFile) { Message message = ERR_SUBCMDPARSER_CANNOT_READ_PROPERTIES_FILE.get( String.valueOf(propertiesFile), getExceptionMessage(e)); throw new ArgumentException(message, e); } } parseArguments(rawArguments, argumentProperties); } /** * Parses the provided set of arguments and updates the information associated * with this parser accordingly. Default values for unspecified arguments may @@ -819,7 +767,7 @@ { if (subCommand == null) { if (argName.equals("help")) if (argName.equals(OPTION_LONG_HELP)) { // "--help" will always be interpreted as requesting usage // information. @@ -850,7 +798,7 @@ a = subCommand.getArgument(argName); if (a == null) { if (argName.equals("help")) if (argName.equals(OPTION_LONG_HELP)) { // "--help" will always be interpreted as requesting usage // information. @@ -1401,8 +1349,8 @@ else { // There are no spaces in the first 74 columns. // See if there is one after that point. If so, then break there. // If not, then don't break at all. // See if there is one after that point. // If so, then break there. If not, then don't break at all. spacePos = s.indexOf(' '); if (spacePos > 0) { @@ -1430,8 +1378,6 @@ } } /** * Retrieves a string containing usage information based on the defined * arguments. @@ -1765,8 +1711,8 @@ } buffer.append(EOL); indentAndWrap(Message.raw(INDENT), a.getDescription(), buffer); indentAndWrap(Message.raw(INDENT), a.getDescription(), buffer); if (a.needsValue() && a.getDefaultValue() != null && a.getDefaultValue().length() > 0) @@ -1810,8 +1756,8 @@ else { // There are no spaces in the first actualSize -1 columns. // See if there is one after that point. If so, then break there. // If not, then don't break at all. // See if there is one after that point. // If so, then break there. If not, then don't break at all. spacePos = s.indexOf(' '); if (spacePos > 0) { @@ -1860,11 +1806,7 @@ @Override public boolean isVersionArgumentPresent() { if (!super.isVersionArgumentPresent()) { return versionPresent; } return true; return super.isVersionArgumentPresent() && !versionPresent; } /** opends/tests/unit-tests-testng/src/server/org/opends/server/tools/dsconfig/DsconfigOptionsTestCase.java
@@ -21,62 +21,49 @@ * * CDDL HEADER END * * Copyright 2011 ForgeRock AS * Copyright 2011-2013 ForgeRock AS */ package org.opends.server.tools.dsconfig; import org.opends.server.DirectoryServerTestCase; import org.opends.server.TestCaseUtils; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.opends.server.TestCaseUtils; import org.opends.server.DirectoryServerTestCase; import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*; import static org.testng.Assert.*; import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*; /** * A set of test cases for the dsservice tool. * A set of test cases for the dsconfig tool. */ @SuppressWarnings("javadoc") public class DsconfigOptionsTestCase extends DirectoryServerTestCase { /** * Ensures that the Directory Server is running and performs other necessary * setup. * * @throws Exception If an unexpected problem occurs. */ @BeforeClass() public void before() throws Exception public void before() throws Exception { TestCaseUtils.startServer(); } /** * Ensures ADS is removed. * @throws Exception If an unexpected problem occurs. */ @AfterClass() public void afterClass() throws Exception public void afterClass() throws Exception { } /** * Tests that multiple "--set" option cannot be used with a singlevalued * property * * @throws Exception If an unexpected problem occurs. */ @Test() public void testMultipleSetSingleValuedProperty() throws Exception public void testMultipleSetSingleValuedProperty() throws Exception { String[] args = { @@ -89,22 +76,15 @@ "--set", "idle-time-limit:10000ms", "--set", "idle-time-limit:1000ms" }; assertFalse(DSConfig.main(args, false, System.out, System.err) == SUCCESSFUL.getReturnCode()); assertTrue(dsconfigMain(args) != SUCCESSFUL.getReturnCode()); } /** * Tests that multiple "--set" option are allowed to be used with a multivalued * property (see OPENDJ-255) * * @throws Exception If an unexpected problem occurs. */ @Test() public void testMultipleSetMultiValuedProperty() throws Exception public void testMultipleSetMultiValuedProperty() throws Exception { String[] args = { @@ -117,16 +97,23 @@ "--no-prompt", "--set", "denied-client:1.1.1.1", "--set", "denied-client:2.2.2.2" }; assertEquals(DSConfig.main(args, false, System.out, System.err), SUCCESSFUL.getReturnCode()); assertEquals(dsconfigMain(args), SUCCESSFUL.getReturnCode()); } public void testGenerateDoc() throws Exception { System.setProperty("org.forgerock.opendj.gendoc", "true"); String[] args = { "--no-prompt", "-?", }; assertEquals(dsconfigMain(args), CANNOT_INITIALIZE_ARGS.getReturnCode()); } private int dsconfigMain(String[] args) { return DSConfig.main(args, false, System.out, System.err); } }