001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.util.cli; 029 030 import java.util.ArrayList; 031 import java.util.HashSet; 032 import java.util.List; 033 034 import org.opends.server.util.SetupUtils; 035 import org.opends.server.util.args.Argument; 036 import org.opends.server.util.args.BooleanArgument; 037 import org.opends.server.util.args.FileBasedArgument; 038 039 /** 040 * Class used to be able to generate the non interactive mode. 041 * 042 */ 043 public class CommandBuilder 044 { 045 // The command name. 046 private String commandName; 047 048 // The subcommand name. 049 private String subcommandName; 050 051 private ArrayList<Argument> args = new ArrayList<Argument>(); 052 private HashSet<Argument> obfuscatedArgs = new HashSet<Argument>(); 053 054 // The value used to display arguments that must be obfuscated (such as 055 // passwords). This does not require localization (since the output of 056 // command builder by its nature is not localized). 057 private final static String OBFUSCATED_VALUE = "******"; 058 059 /** 060 * The constructor for the CommandBuilder. 061 * @param commandName the command name. 062 */ 063 public CommandBuilder(String commandName) 064 { 065 this(commandName, null); 066 } 067 068 /** 069 * The constructor for the CommandBuilder. 070 * @param commandName the command name. 071 * @param subcommandName the subcommand name. 072 */ 073 public CommandBuilder(String commandName, String subcommandName) 074 { 075 this.commandName = commandName; 076 this.subcommandName = subcommandName; 077 } 078 079 /** 080 * Adds an argument to the list of the command builder. 081 * @param argument the argument to be added. 082 */ 083 public void addArgument(Argument argument) 084 { 085 // We use an ArrayList to be able to provide the possibility of updating 086 // the position of the attributes. 087 if (!args.contains(argument)) 088 { 089 args.add(argument); 090 } 091 } 092 093 /** 094 * Adds an argument whose values must be obfuscated (passwords for instance). 095 * @param argument the argument to be added. 096 */ 097 public void addObfuscatedArgument(Argument argument) 098 { 099 addArgument(argument); 100 obfuscatedArgs.add(argument); 101 } 102 103 /** 104 * Removes the provided argument from this CommandBuilder. 105 * @param argument the argument to be removed. 106 * @return <CODE>true</CODE> if the attribute was present and removed and 107 * <CODE>false</CODE> otherwise. 108 */ 109 public boolean removeArgument(Argument argument) 110 { 111 obfuscatedArgs.remove(argument); 112 return args.remove(argument); 113 } 114 115 /** 116 * Appends the arguments of another command builder to this command builder. 117 * @param builder the CommandBuilder to append. 118 */ 119 public void append(CommandBuilder builder) 120 { 121 for (Argument arg : builder.args) 122 { 123 if (builder.isObfuscated(arg)) 124 { 125 addObfuscatedArgument(arg); 126 } 127 else 128 { 129 addArgument(arg); 130 } 131 } 132 } 133 134 /** 135 * Returns the String representation of this command builder (i.e. what we 136 * want to show to the user). 137 * @return the String representation of this command builder (i.e. what we 138 * want to show to the user). 139 */ 140 public String toString() 141 { 142 return toString(false); 143 } 144 145 /** 146 * Returns the String representation of this command builder (i.e. what we 147 * want to show to the user). 148 * @param showObfuscated displays in clear the obfuscated values. 149 * @return the String representation of this command builder (i.e. what we 150 * want to show to the user). 151 */ 152 private String toString(boolean showObfuscated) 153 { 154 StringBuilder builder = new StringBuilder(); 155 builder.append(commandName); 156 if (subcommandName != null) 157 { 158 builder.append(" "+subcommandName); 159 } 160 for (Argument arg : args) 161 { 162 String argName; 163 if (arg.getLongIdentifier() != null) 164 { 165 argName = "--"+arg.getLongIdentifier(); 166 } 167 else 168 { 169 argName = "-"+arg.getShortIdentifier(); 170 } 171 String separator; 172 if (SetupUtils.isWindows()) 173 { 174 separator = " "; 175 } 176 else 177 { 178 separator = " \\\n "; 179 } 180 181 if (arg instanceof BooleanArgument) 182 { 183 builder.append(separator+argName); 184 } 185 else if (arg instanceof FileBasedArgument) 186 { 187 for (String value : 188 ((FileBasedArgument)arg).getNameToValueMap().keySet()) 189 { 190 builder.append(separator+argName+" "); 191 if (isObfuscated(arg) && !showObfuscated) 192 { 193 value = OBFUSCATED_VALUE; 194 } 195 else 196 { 197 value = escapeValue(value); 198 } 199 builder.append(value); 200 } 201 } 202 else 203 { 204 for (String value : arg.getValues()) 205 { 206 builder.append(separator+argName+" "); 207 if (isObfuscated(arg) && !showObfuscated) 208 { 209 value = OBFUSCATED_VALUE; 210 } 211 else 212 { 213 value = escapeValue(value); 214 } 215 builder.append(value); 216 } 217 } 218 } 219 return builder.toString(); 220 } 221 222 /** 223 * Clears the arguments. 224 */ 225 public void clearArguments() 226 { 227 args.clear(); 228 obfuscatedArgs.clear(); 229 } 230 231 /** 232 * Returns the list of arguments. 233 * @return the list of arguments. 234 */ 235 public List<Argument> getArguments() 236 { 237 return args; 238 } 239 240 /** 241 * Tells whether the provided argument's values must be obfuscated or not. 242 * @param argument the argument to handle. 243 * @return <CODE>true</CODE> if the attribute's values must be obfuscated and 244 * <CODE>false</CODE> otherwise. 245 */ 246 private boolean isObfuscated(Argument argument) 247 { 248 return obfuscatedArgs.contains(argument); 249 } 250 251 // Chars that require special treatment when passing them to command-line. 252 private final char[] charsToEscape = {' ', '\t', '\n', '|', ';', '<', '>', 253 '(', ')', '$', '`', '\\', '"', '\''}; 254 /** 255 * This method simply takes a value and tries to transform it (with escape or 256 * '"') characters so that it can be used in a command line. 257 * @param value the String to be treated. 258 * @return the transformed value. 259 */ 260 private String escapeValue(String value) 261 { 262 StringBuilder b = new StringBuilder(); 263 if (SetupUtils.isUnix()) 264 { 265 for (int i=0 ; i<value.length(); i++) 266 { 267 char c = value.charAt(i); 268 boolean charToEscapeFound = false; 269 for (int j=0; j<charsToEscape.length && !charToEscapeFound; j++) 270 { 271 charToEscapeFound = c == charsToEscape[j]; 272 } 273 if (charToEscapeFound) 274 { 275 b.append('\\'); 276 } 277 b.append(c); 278 } 279 } 280 else 281 { 282 b.append('"').append(value).append('"'); 283 } 284 285 return b.toString(); 286 } 287 }