/* * 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(); } }