1 19 20 package org.netbeans.api.sendopts; 21 22 import java.io.File ; 23 import java.io.InputStream ; 24 import java.io.OutputStream ; 25 import java.io.PrintWriter ; 26 import java.util.ArrayList ; 27 import java.util.Collections ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.LinkedHashMap ; 31 import java.util.LinkedHashSet ; 32 import java.util.Locale ; 33 import java.util.Map ; 34 import org.netbeans.modules.sendopts.OptionImpl; 35 import org.netbeans.spi.sendopts.Env; 36 import org.netbeans.spi.sendopts.Option; 37 import org.netbeans.spi.sendopts.OptionProcessor; 38 import org.openide.util.Lookup; 39 import org.openide.util.NbBundle; 40 41 47 public final class CommandLine { 48 49 private static final int ERROR_BASE = 50345; 50 51 52 CommandLine() { 53 } 54 55 59 public static CommandLine getDefault() { 60 return new CommandLine(); 61 } 62 63 68 public void process(String [] args) throws CommandException { 69 process(args, null, null, null, null); 70 } 71 72 81 public void process(String [] args, InputStream is, OutputStream os, OutputStream err, File currentDir) throws CommandException { 82 if (is == null) { 83 is = System.in; 84 } 85 if (os == null) { 86 os = System.out; 87 } 88 if (err == null) { 89 err = System.err; 90 } 91 if (currentDir == null) { 92 currentDir = new File (System.getProperty("user.dir")); } 94 Env env = OptionImpl.Trampoline.DEFAULT.create(is, os, err, currentDir); 95 96 97 ArrayList <String > additionalParams = new ArrayList <String >(); 98 ArrayList <OptionImpl> opts = new ArrayList <OptionImpl>(); 99 OptionImpl acceptsAdons = null; 100 101 OptionImpl[] mainOptions = getOptions(); 102 LinkedHashSet <OptionImpl> allOptions = new LinkedHashSet <OptionImpl>(); 103 for (int i = 0; i < mainOptions.length; i++) { 104 mainOptions[i] = mainOptions[i].addWorkingCopy(allOptions); 105 } 106 OptionImpl[] arr = allOptions.toArray(new OptionImpl[0]); 107 108 boolean optionMode = true; 109 ARGS: for (int i = 0; i < args.length; i++) { 110 if (args[i] == null) { 111 continue ARGS; 112 } 113 114 if (optionMode) { 115 if (args[i].startsWith("--")) { 116 if (args[i].length() == 2) { 117 optionMode = false; 118 continue ARGS; 119 } 120 121 String text = args[i].substring(2); 122 String value = null; 123 int textEqual = text.indexOf('='); 124 if (textEqual >= 0) { 125 value = text.substring(textEqual + 1); 127 text = text.substring(0, textEqual); 128 } 129 OptionImpl opt = findByLongName (text, arr); 130 if (opt == null) { 131 throw new CommandException(args[i], ERROR_BASE + 1); 132 } 133 if (opt.getArgumentType() == 1 && value == null) { 134 for(;;) { 136 if (++i == args.length) { 137 throw new CommandException(NbBundle.getMessage(CommandLine.class, "MSG_MissingArgument", "--" + opt.getLongName()), ERROR_BASE + 2); } 139 140 if (args[i].equals("--")) { 141 optionMode = false; 142 continue; 143 } 144 145 if (optionMode && args[i].startsWith("-")) { 146 throw new CommandException(NbBundle.getMessage(CommandLine.class, "MSG_MissingArgument", "--" + opt.getLongName()), ERROR_BASE + 2); } 148 149 break; 150 } 151 152 153 154 value = args[i]; 155 } 156 157 158 if (value != null) { 159 if (opt.getArgumentType() != 1 && opt.getArgumentType() != 2) { 160 throw new CommandException("Option " + opt + " cannot have value " + value, ERROR_BASE + 2); 161 } 162 163 opt.associateValue(value); 164 } 165 166 if (opt.getArgumentType() == 3) { 167 if (acceptsAdons != null) { 168 String oName1 = findOptionName(acceptsAdons, args); 169 String oName2 = findOptionName(opt, args); 170 String msg = NbBundle.getMessage(CommandLine.class, "MSG_CannotTogether", oName1, oName2); throw new CommandException(msg, ERROR_BASE + 3); 172 } 173 acceptsAdons = opt; 174 } 175 176 opts.add(opt); 177 continue ARGS; 178 } else if (args[i].startsWith("-") && args[i].length() > 1) { 179 for (int j = 1; j < args[i].length(); j++) { 180 char ch = args[i].charAt(j); 181 OptionImpl opt = findByShortName(ch, arr); 182 if (opt == null) { 183 throw new CommandException("Unknown option " + args[i], ERROR_BASE + 1); 184 } 185 if (args[i].length() == j + 1 && opt.getArgumentType() == 1) { 186 throw new CommandException(NbBundle.getMessage(CommandLine.class, "MSG_MissingArgument", args[i]), ERROR_BASE + 2); 187 } 188 189 if (args[i].length() > j && (opt.getArgumentType() == 1 || opt.getArgumentType() == 2)) { 190 opt.associateValue(args[i].substring(j + 1)); 191 j = args[i].length(); 192 } 193 if (opt.getArgumentType() == 3) { 194 if (acceptsAdons != null) { 195 String oName1 = findOptionName(acceptsAdons, args); 196 String oName2 = findOptionName(opt, args); 197 String msg = NbBundle.getMessage(CommandLine.class, "MSG_CannotTogether", oName1, oName2); throw new CommandException(msg, ERROR_BASE + 3); 199 } 200 acceptsAdons = opt; 201 } 202 opts.add(opt); 203 } 204 continue ARGS; 205 } 206 } 207 208 additionalParams.add(args[i]); 209 } 210 211 if (acceptsAdons == null && !additionalParams.isEmpty()) { 212 for (int i = 0; i < arr.length; i++) { 213 if (arr[i].getArgumentType() == 4) { 214 if (acceptsAdons != null) { 215 throw new CommandException("There cannot be two default options: " + acceptsAdons + " and " + arr[i], ERROR_BASE + 3); 216 } 217 acceptsAdons = arr[i]; 218 opts.add(acceptsAdons); 219 } 220 } 221 if (acceptsAdons == null) { 222 throw new CommandException("There are params but noone wants to proces them: " + additionalParams, ERROR_BASE + 2); 223 } 224 225 } 226 227 OptionImpl.Appearance[] postProcess = new OptionImpl.Appearance[mainOptions.length]; 228 { 229 HashSet <OptionImpl> used = new HashSet <OptionImpl>(opts); 230 for (int i = 0; i < mainOptions.length; i++) { 231 OptionImpl.Appearance res = mainOptions[i].checkConsistent(used); 232 postProcess[i] = res; 233 if (res.isThere()) { 234 mainOptions[i].markConsistent(res); 235 } 236 241 } 242 } 243 244 245 { 246 HashSet <OptionImpl> used = new HashSet <OptionImpl>(opts); 247 for (int i = 0; i < mainOptions.length; i++) { 248 if (postProcess[i].isError()) { 249 OptionImpl error = mainOptions[i].findNotUsedOption(used); 250 if (error != null) { 251 throw new CommandException(postProcess[i].errorMessage(args), ERROR_BASE + 4); 252 } 253 } 254 } 255 } 256 257 Map <OptionProcessor,Map <Option,String []>> providers = new LinkedHashMap <OptionProcessor,Map <Option,String []>>(); 258 { 259 for (int i = 0; i < mainOptions.length; i++) { 260 if (postProcess[i].isThere()) { 261 Map <Option,String []> param = providers.get(mainOptions[i].getProvider()); 262 if (param == null) { 263 param = new HashMap <Option,String []>(); 264 providers.put(mainOptions[i].getProvider(), param); 265 } 266 mainOptions[i].process(additionalParams.toArray(new String [0]), param); 267 } 268 } 269 } 270 271 for (Map.Entry <OptionProcessor, Map <Option, String []>> pair : providers.entrySet()) { 272 OptionImpl.Trampoline.DEFAULT.process(pair.getKey(), env, pair.getValue()); 273 } 274 } 275 276 282 public void usage(PrintWriter w) { 283 OptionImpl[] mainOptions = getOptions(); 284 LinkedHashSet <OptionImpl> allOptions = new LinkedHashSet <OptionImpl>(); 285 for (int i = 0; i < mainOptions.length; i++) { 286 mainOptions[i].addWorkingCopy(allOptions); 287 } 288 OptionImpl[] arr = allOptions.toArray(new OptionImpl[0]); 289 290 int max = 25; 291 String [] prefixes = new String [arr.length]; 292 for (int i = 0; i < arr.length; i++) { 293 StringBuffer sb = new StringBuffer (); 294 295 String ownDisplay = OptionImpl.Trampoline.DEFAULT.getDisplayName(arr[i].getOption(), Locale.getDefault()); 296 if (ownDisplay != null) { 297 sb.append(ownDisplay); 298 } else { 299 String sep = ""; 300 if (arr[i].getShortName() != -1) { 301 sb.append('-'); 302 sb.append((char)arr[i].getShortName()); 303 sep = ", "; 304 } 305 if (arr[i].getLongName() != null) { 306 sb.append(sep); 307 sb.append("--"); sb.append(arr[i].getLongName()); 309 } else { 310 if (sep.length() == 0) { 311 continue; 312 } 313 } 314 315 switch (arr[i].getArgumentType()) { 316 case 0: break; 317 case 1: 318 sb.append(' '); 319 sb.append(NbBundle.getMessage(CommandLine.class, "MSG_OneArg")); break; 321 case 2: 322 sb.append(' '); 323 sb.append(NbBundle.getMessage(CommandLine.class, "MSG_OptionalArg")); break; 325 case 3: 326 sb.append(' '); 327 sb.append(NbBundle.getMessage(CommandLine.class, "MSG_AddionalArgs")); break; 329 default: 330 assert false; 331 } 332 } 333 334 if (sb.length() > max) { 335 max = sb.length(); 336 } 337 338 prefixes[i] = sb.toString(); 339 } 340 341 for (int i = 0; i < arr.length; i++) { 342 if (prefixes[i] != null) { 343 w.print(" "); w.print(prefixes[i]); 345 for (int j = prefixes[i].length(); j < max; j++) { 346 w.print(' '); 347 } 348 w.print(' '); 349 arr[i].usage(w, max); 350 w.println(); 351 } 352 } 353 354 w.flush(); 355 } 356 357 private OptionImpl[] getOptions() { 358 ArrayList <OptionImpl> arr = new ArrayList <OptionImpl>(); 359 360 for (OptionProcessor p : Lookup.getDefault().lookupAll(OptionProcessor.class)) { 361 org.netbeans.spi.sendopts.Option[] all = OptionImpl.Trampoline.DEFAULT.getOptions(p); 362 for (int i = 0; i < all.length; i++) { 363 arr.add(OptionImpl.cloneImpl(OptionImpl.find(all[i]), all[i], p)); 364 } 365 } 366 367 return arr.toArray(new OptionImpl[0]); 368 } 369 370 private OptionImpl findByLongName(String lng, OptionImpl[] arr) { 371 boolean abbrev = false; 372 OptionImpl best = null; 373 for (int i = 0; i < arr.length; i++) { 374 String on = arr[i].getLongName(); 375 if (on == null) { 376 continue; 377 } 378 if (lng.equals(on)) { 379 return arr[i]; 380 } 381 if (on.startsWith(lng)) { 382 abbrev = best == null; 383 best = arr[i]; 384 } 385 } 386 387 return abbrev ? best : null; 388 } 389 390 private OptionImpl findByShortName(char ch, OptionImpl[] arr) { 391 for (int i = 0; i < arr.length; i++) { 392 if (ch == arr[i].getShortName()) { 393 return arr[i]; 394 } 395 } 396 return null; 397 } 398 399 private static String findOptionName(OptionImpl opt, String [] args) { 400 for(int i = 0; i < args.length; i++) { 401 if (!args[i].startsWith("-")) { 402 continue; 403 } 404 405 if (args[i].startsWith("--")) { 406 String text = args[i].substring(2); 407 int textEqual = text.indexOf('='); 408 if (textEqual >= 0) { 409 text = text.substring(0, textEqual); 411 } 412 if (text.startsWith(opt.getLongName())) { 413 return args[i]; 414 } 415 } else { 416 if (opt.getShortName() == args[i].charAt(1)) { 417 return "-" + (char)opt.getShortName(); 418 } 419 } 420 } 421 422 return opt.toString(); 423 } 424 425 } 426 | Popular Tags |