/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008-2009 Sun Microsystems, Inc.
*/
package org.opends.server.util.cli;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.opends.server.util.SetupUtils;
import org.opends.server.util.args.Argument;
import org.opends.server.util.args.BooleanArgument;
import org.opends.server.util.args.FileBasedArgument;
/**
* Class used to be able to generate the non interactive mode.
*
*/
public class CommandBuilder
{
// The command name.
private String commandName;
// The subcommand name.
private String subcommandName;
private ArrayList<Argument> args = new ArrayList<Argument>();
private HashSet<Argument> obfuscatedArgs = new HashSet<Argument>();
/**
* The value used to display arguments that must be obfuscated (such as
* passwords). This does not require localization (since the output of
* command builder by its nature is not localized).
*/
public final static String OBFUSCATED_VALUE = "******";
/**
* The separator used to link the lines of the resulting command-lines.
*/
public final static String LINE_SEPARATOR;
static
{
if (SetupUtils.isWindows())
{
LINE_SEPARATOR = " ";
}
else
{
LINE_SEPARATOR = " \\\n ";
}
}
/**
* The separator used to link the lines of the resulting command-lines in
* HTML format.
*/
public final static String HTML_LINE_SEPARATOR;
static
{
if (SetupUtils.isWindows())
{
HTML_LINE_SEPARATOR = " ";
}
else
{
HTML_LINE_SEPARATOR =
" \\<br> ";
}
}
/**
* The constructor for the CommandBuilder.
* @param commandName the command name.
*/
public CommandBuilder(String commandName)
{
this(commandName, null);
}
/**
* The constructor for the CommandBuilder.
* @param commandName the command name.
* @param subcommandName the subcommand name.
*/
public CommandBuilder(String commandName, String subcommandName)
{
this.commandName = commandName;
this.subcommandName = subcommandName;
}
/**
* Adds an argument to the list of the command builder.
* @param argument the argument to be added.
*/
public void addArgument(Argument argument)
{
// We use an ArrayList to be able to provide the possibility of updating
// the position of the attributes.
if (!args.contains(argument))
{
args.add(argument);
}
}
/**
* Adds an argument whose values must be obfuscated (passwords for instance).
* @param argument the argument to be added.
*/
public void addObfuscatedArgument(Argument argument)
{
addArgument(argument);
obfuscatedArgs.add(argument);
}
/**
* Removes the provided argument from this CommandBuilder.
* @param argument the argument to be removed.
* @return <CODE>true</CODE> if the attribute was present and removed and
* <CODE>false</CODE> otherwise.
*/
public boolean removeArgument(Argument argument)
{
obfuscatedArgs.remove(argument);
return args.remove(argument);
}
/**
* Appends the arguments of another command builder to this command builder.
* @param builder the CommandBuilder to append.
*/
public void append(CommandBuilder builder)
{
for (Argument arg : builder.args)
{
if (builder.isObfuscated(arg))
{
addObfuscatedArgument(arg);
}
else
{
addArgument(arg);
}
}
}
/**
* Returns the String representation of this command builder (i.e. what we
* want to show to the user).
* @return the String representation of this command builder (i.e. what we
* want to show to the user).
*/
public String toString()
{
return toString(false, LINE_SEPARATOR);
}
/**
* Returns the String representation of this command builder (i.e. what we
* want to show to the user).
* @param lineSeparator the String to be used to separate lines of the
* command-builder.
* @return the String representation of this command builder (i.e. what we
* want to show to the user).
*/
public String toString(String lineSeparator)
{
return toString(false, lineSeparator);
}
/**
* Returns the String representation of this command builder (i.e. what we
* want to show to the user).
* @param showObfuscated displays in clear the obfuscated values.
* @param lineSeparator the String to be used to separate lines of the
* command-builder.
* @return the String representation of this command builder (i.e. what we
* want to show to the user).
*/
private String toString(boolean showObfuscated, String lineSeparator)
{
StringBuilder builder = new StringBuilder();
builder.append(commandName);
if (subcommandName != null)
{
builder.append(" "+subcommandName);
}
for (Argument arg : args)
{
// This CLI is always using SSL, and the argument has been removed from
// the user interface
if (arg.getName().equals("useSSL") ) {
continue;
}
String argName;
if (arg.getLongIdentifier() != null)
{
argName = "--"+arg.getLongIdentifier();
}
else
{
argName = "-"+arg.getShortIdentifier();
}
if (arg instanceof BooleanArgument)
{
builder.append(lineSeparator+argName);
}
else if (arg instanceof FileBasedArgument)
{
for (String value :
((FileBasedArgument)arg).getNameToValueMap().keySet())
{
builder.append(lineSeparator+argName+" ");
if (isObfuscated(arg) && !showObfuscated)
{
value = OBFUSCATED_VALUE;
}
else
{
value = escapeValue(value);
}
builder.append(value);
}
}
else
{
for (String value : arg.getValues())
{
builder.append(lineSeparator+argName+" ");
if (isObfuscated(arg) && !showObfuscated)
{
value = OBFUSCATED_VALUE;
}
else
{
value = escapeValue(value);
}
builder.append(value);
}
}
}
return builder.toString();
}
/**
* Clears the arguments.
*/
public void clearArguments()
{
args.clear();
obfuscatedArgs.clear();
}
/**
* Returns the list of arguments.
* @return the list of arguments.
*/
public List<Argument> getArguments()
{
return args;
}
/**
* Tells whether the provided argument's values must be obfuscated or not.
* @param argument the argument to handle.
* @return <CODE>true</CODE> if the attribute's values must be obfuscated and
* <CODE>false</CODE> otherwise.
*/
public boolean isObfuscated(Argument argument)
{
return obfuscatedArgs.contains(argument);
}
// Chars that require special treatment when passing them to command-line.
private final static char[] charsToEscape = {' ', '\t', '\n', '|', ';', '<',
'>', '(', ')', '$', '`', '\\', '"', '\''};
/**
* This method simply takes a value and tries to transform it (with escape or
* '"') characters so that it can be used in a command line.
* @param value the String to be treated.
* @return the transformed value.
*/
public static String escapeValue(String value)
{
StringBuilder b = new StringBuilder();
if (SetupUtils.isUnix())
{
for (int i=0 ; i<value.length(); i++)
{
char c = value.charAt(i);
boolean charToEscapeFound = false;
for (int j=0; j<charsToEscape.length && !charToEscapeFound; j++)
{
charToEscapeFound = c == charsToEscape[j];
}
if (charToEscapeFound)
{
b.append('\\');
}
b.append(c);
}
}
else
{
b.append('"').append(value).append('"');
}
return b.toString();
}
}