src/share/classes/com/sun/tools/javadoc/Start.java

Thu, 25 Oct 2012 11:09:36 -0700

author
jjg
date
Thu, 25 Oct 2012 11:09:36 -0700
changeset 1374
c002fdee76fd
parent 1359
25e14ad23cef
child 1391
ef3ad754f5c7
permissions
-rw-r--r--

7200915: convert TypeTags from a series of small ints to an enum
Reviewed-by: jjg, mcimadamore
Contributed-by: vicente.romero@oracle.com

duke@1 1 /*
jjg@1357 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
duke@1 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1 4 *
duke@1 5 * This code is free software; you can redistribute it and/or modify it
duke@1 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
duke@1 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
duke@1 10 *
duke@1 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@1 15 * accompanied this code).
duke@1 16 *
duke@1 17 * You should have received a copy of the GNU General Public License version
duke@1 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@1 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
duke@1 24 */
duke@1 25
duke@1 26 package com.sun.tools.javadoc;
duke@1 27
jjg@1357 28 import java.io.File;
jjg@1357 29 import java.io.FileNotFoundException;
jjg@1357 30 import java.io.IOException;
jjg@1357 31 import java.io.PrintWriter;
jjg@1357 32 import java.util.StringTokenizer;
jjg@1357 33
duke@1 34 import com.sun.javadoc.*;
duke@1 35 import com.sun.tools.javac.main.CommandLine;
duke@1 36 import com.sun.tools.javac.util.Context;
duke@1 37 import com.sun.tools.javac.util.List;
duke@1 38 import com.sun.tools.javac.util.ListBuffer;
jjg@1135 39 import com.sun.tools.javac.util.Log;
duke@1 40 import com.sun.tools.javac.util.Options;
duke@1 41 import static com.sun.tools.javac.code.Flags.*;
duke@1 42
duke@1 43 /**
duke@1 44 * Main program of Javadoc.
duke@1 45 * Previously named "Main".
duke@1 46 *
jjg@1359 47 * <p><b>This is NOT part of any supported API.
jjg@1359 48 * If you write code that depends on this, you do so at your own risk.
jjg@1359 49 * This code and its internal interfaces are subject to change or
jjg@1359 50 * deletion without notice.</b>
jjg@1359 51 *
duke@1 52 * @since 1.2
duke@1 53 * @author Robert Field
duke@1 54 * @author Neal Gafter (rewrite)
duke@1 55 */
duke@1 56 class Start {
duke@1 57
duke@1 58 private final String defaultDocletClassName;
jjg@129 59 private final ClassLoader docletParentClassLoader;
duke@1 60
duke@1 61 private static final String javadocName = "javadoc";
duke@1 62
duke@1 63 private static final String standardDocletClassName =
duke@1 64 "com.sun.tools.doclets.standard.Standard";
duke@1 65
duke@1 66 private ListBuffer<String[]> options = new ListBuffer<String[]>();
duke@1 67
duke@1 68 private ModifierFilter showAccess = null;
duke@1 69
duke@1 70 private long defaultFilter = PUBLIC | PROTECTED;
duke@1 71
duke@1 72 private Messager messager;
duke@1 73
duke@1 74 String docLocale = "";
duke@1 75
duke@1 76 boolean breakiterator = false;
duke@1 77 boolean quiet = false;
duke@1 78 String encoding = null;
duke@1 79
duke@1 80 private DocletInvoker docletInvoker;
duke@1 81
duke@1 82 /* Treat warnings as errors. */
duke@1 83 private boolean rejectWarnings = false;
duke@1 84
duke@1 85 Start(String programName,
duke@1 86 PrintWriter errWriter,
duke@1 87 PrintWriter warnWriter,
duke@1 88 PrintWriter noticeWriter,
duke@1 89 String defaultDocletClassName) {
jjg@129 90 this(programName, errWriter, warnWriter, noticeWriter, defaultDocletClassName, null);
jjg@129 91 }
jjg@129 92
jjg@129 93 Start(String programName,
jjg@129 94 PrintWriter errWriter,
jjg@129 95 PrintWriter warnWriter,
jjg@129 96 PrintWriter noticeWriter,
jjg@129 97 String defaultDocletClassName,
jjg@129 98 ClassLoader docletParentClassLoader) {
jjg@584 99 Context tempContext = new Context(); // interim context until option decoding completed
jjg@584 100 messager = new Messager(tempContext, programName, errWriter, warnWriter, noticeWriter);
duke@1 101 this.defaultDocletClassName = defaultDocletClassName;
jjg@129 102 this.docletParentClassLoader = docletParentClassLoader;
duke@1 103 }
duke@1 104
duke@1 105 Start(String programName, String defaultDocletClassName) {
jjg@129 106 this(programName, defaultDocletClassName, null);
jjg@129 107 }
jjg@129 108
jjg@129 109 Start(String programName, String defaultDocletClassName,
jjg@129 110 ClassLoader docletParentClassLoader) {
jjg@584 111 Context tempContext = new Context(); // interim context until option decoding completed
jjg@584 112 messager = new Messager(tempContext, programName);
duke@1 113 this.defaultDocletClassName = defaultDocletClassName;
jjg@129 114 this.docletParentClassLoader = docletParentClassLoader;
jjg@129 115 }
jjg@129 116
jjg@129 117 Start(String programName, ClassLoader docletParentClassLoader) {
jjg@129 118 this(programName, standardDocletClassName, docletParentClassLoader);
duke@1 119 }
duke@1 120
duke@1 121 Start(String programName) {
duke@1 122 this(programName, standardDocletClassName);
duke@1 123 }
duke@1 124
jjg@129 125 Start(ClassLoader docletParentClassLoader) {
jjg@129 126 this(javadocName, docletParentClassLoader);
jjg@129 127 }
jjg@129 128
duke@1 129 Start() {
duke@1 130 this(javadocName);
duke@1 131 }
duke@1 132
duke@1 133 /**
duke@1 134 * Usage
duke@1 135 */
duke@1 136 private void usage() {
duke@1 137 messager.notice("main.usage");
duke@1 138
duke@1 139 // let doclet print usage information (does nothing on error)
duke@1 140 if (docletInvoker != null) {
duke@1 141 docletInvoker.optionLength("-help");
duke@1 142 }
duke@1 143 }
duke@1 144
duke@1 145 /**
jjg@584 146 * Usage
jjg@584 147 */
jjg@584 148 private void Xusage() {
jjg@584 149 messager.notice("main.Xusage");
jjg@584 150 }
jjg@584 151
jjg@584 152 /**
duke@1 153 * Exit
duke@1 154 */
duke@1 155 private void exit() {
duke@1 156 messager.exit();
duke@1 157 }
duke@1 158
duke@1 159
duke@1 160 /**
duke@1 161 * Main program - external wrapper
duke@1 162 */
jjg@127 163 int begin(String... argv) {
duke@1 164 boolean failed = false;
duke@1 165
duke@1 166 try {
duke@1 167 failed = !parseAndExecute(argv);
duke@1 168 } catch(Messager.ExitJavadoc exc) {
duke@1 169 // ignore, we just exit this way
duke@1 170 } catch (OutOfMemoryError ee) {
duke@1 171 messager.error(null, "main.out.of.memory");
duke@1 172 failed = true;
duke@1 173 } catch (Error ee) {
jjg@1135 174 ee.printStackTrace(System.err);
duke@1 175 messager.error(null, "main.fatal.error");
duke@1 176 failed = true;
duke@1 177 } catch (Exception ee) {
jjg@1135 178 ee.printStackTrace(System.err);
duke@1 179 messager.error(null, "main.fatal.exception");
duke@1 180 failed = true;
duke@1 181 } finally {
duke@1 182 messager.exitNotice();
duke@1 183 messager.flush();
duke@1 184 }
duke@1 185 failed |= messager.nerrors() > 0;
duke@1 186 failed |= rejectWarnings && messager.nwarnings() > 0;
duke@1 187 return failed ? 1 : 0;
duke@1 188 }
duke@1 189
duke@1 190 private void addToList(ListBuffer<String> list, String str){
duke@1 191 StringTokenizer st = new StringTokenizer(str, ":");
duke@1 192 String current;
duke@1 193 while(st.hasMoreTokens()){
duke@1 194 current = st.nextToken();
duke@1 195 list.append(current);
duke@1 196 }
duke@1 197 }
duke@1 198
duke@1 199 /**
duke@1 200 * Main program - internal
duke@1 201 */
jjg@127 202 private boolean parseAndExecute(String... argv) throws IOException {
duke@1 203 long tm = System.currentTimeMillis();
duke@1 204
duke@1 205 ListBuffer<String> javaNames = new ListBuffer<String>();
duke@1 206
duke@1 207 // Preprocess @file arguments
duke@1 208 try {
duke@1 209 argv = CommandLine.parse(argv);
duke@1 210 } catch (FileNotFoundException e) {
duke@1 211 messager.error(null, "main.cant.read", e.getMessage());
duke@1 212 exit();
duke@1 213 } catch (IOException e) {
jjg@1135 214 e.printStackTrace(System.err);
duke@1 215 exit();
duke@1 216 }
duke@1 217
duke@1 218 setDocletInvoker(argv);
duke@1 219 ListBuffer<String> subPackages = new ListBuffer<String>();
duke@1 220 ListBuffer<String> excludedPackages = new ListBuffer<String>();
jjg@584 221
jjg@584 222 Context context = new Context();
jjg@584 223 // Setup a new Messager, using the same initial parameters as the
jjg@584 224 // existing Messager, except that this one will be able to use any
jjg@584 225 // options that may be set up below.
jjg@584 226 Messager.preRegister(context,
jjg@584 227 messager.programName,
jjg@1135 228 messager.getWriter(Log.WriterKind.ERROR),
jjg@1135 229 messager.getWriter(Log.WriterKind.WARNING),
jjg@1135 230 messager.getWriter(Log.WriterKind.NOTICE));
jjg@584 231
duke@1 232 Options compOpts = Options.instance(context);
duke@1 233 boolean docClasses = false;
duke@1 234
duke@1 235 // Parse arguments
duke@1 236 for (int i = 0 ; i < argv.length ; i++) {
duke@1 237 String arg = argv[i];
duke@1 238 if (arg.equals("-subpackages")) {
duke@1 239 oneArg(argv, i++);
duke@1 240 addToList(subPackages, argv[i]);
duke@1 241 } else if (arg.equals("-exclude")){
duke@1 242 oneArg(argv, i++);
duke@1 243 addToList(excludedPackages, argv[i]);
duke@1 244 } else if (arg.equals("-verbose")) {
duke@1 245 setOption(arg);
duke@1 246 compOpts.put("-verbose", "");
duke@1 247 } else if (arg.equals("-encoding")) {
duke@1 248 oneArg(argv, i++);
duke@1 249 encoding = argv[i];
duke@1 250 compOpts.put("-encoding", argv[i]);
duke@1 251 } else if (arg.equals("-breakiterator")) {
duke@1 252 breakiterator = true;
duke@1 253 setOption("-breakiterator");
duke@1 254 } else if (arg.equals("-quiet")) {
duke@1 255 quiet = true;
duke@1 256 setOption("-quiet");
duke@1 257 } else if (arg.equals("-help")) {
duke@1 258 usage();
duke@1 259 exit();
duke@1 260 } else if (arg.equals("-Xclasses")) {
duke@1 261 setOption(arg);
duke@1 262 docClasses = true;
duke@1 263 } else if (arg.equals("-Xwerror")) {
duke@1 264 setOption(arg);
duke@1 265 rejectWarnings = true;
duke@1 266 } else if (arg.equals("-private")) {
duke@1 267 setOption(arg);
duke@1 268 setFilter(ModifierFilter.ALL_ACCESS);
duke@1 269 } else if (arg.equals("-package")) {
duke@1 270 setOption(arg);
duke@1 271 setFilter(PUBLIC | PROTECTED |
duke@1 272 ModifierFilter.PACKAGE );
duke@1 273 } else if (arg.equals("-protected")) {
duke@1 274 setOption(arg);
duke@1 275 setFilter(PUBLIC | PROTECTED );
duke@1 276 } else if (arg.equals("-public")) {
duke@1 277 setOption(arg);
duke@1 278 setFilter(PUBLIC);
duke@1 279 } else if (arg.equals("-source")) {
duke@1 280 oneArg(argv, i++);
duke@1 281 if (compOpts.get("-source") != null) {
duke@1 282 usageError("main.option.already.seen", arg);
duke@1 283 }
duke@1 284 compOpts.put("-source", argv[i]);
duke@1 285 } else if (arg.equals("-prompt")) {
duke@1 286 compOpts.put("-prompt", "-prompt");
duke@1 287 messager.promptOnError = true;
duke@1 288 } else if (arg.equals("-sourcepath")) {
duke@1 289 oneArg(argv, i++);
duke@1 290 if (compOpts.get("-sourcepath") != null) {
duke@1 291 usageError("main.option.already.seen", arg);
duke@1 292 }
duke@1 293 compOpts.put("-sourcepath", argv[i]);
duke@1 294 } else if (arg.equals("-classpath")) {
duke@1 295 oneArg(argv, i++);
duke@1 296 if (compOpts.get("-classpath") != null) {
duke@1 297 usageError("main.option.already.seen", arg);
duke@1 298 }
duke@1 299 compOpts.put("-classpath", argv[i]);
duke@1 300 } else if (arg.equals("-sysclasspath")) {
duke@1 301 oneArg(argv, i++);
duke@1 302 if (compOpts.get("-bootclasspath") != null) {
duke@1 303 usageError("main.option.already.seen", arg);
duke@1 304 }
duke@1 305 compOpts.put("-bootclasspath", argv[i]);
duke@1 306 } else if (arg.equals("-bootclasspath")) {
duke@1 307 oneArg(argv, i++);
duke@1 308 if (compOpts.get("-bootclasspath") != null) {
duke@1 309 usageError("main.option.already.seen", arg);
duke@1 310 }
duke@1 311 compOpts.put("-bootclasspath", argv[i]);
duke@1 312 } else if (arg.equals("-extdirs")) {
duke@1 313 oneArg(argv, i++);
duke@1 314 if (compOpts.get("-extdirs") != null) {
duke@1 315 usageError("main.option.already.seen", arg);
duke@1 316 }
duke@1 317 compOpts.put("-extdirs", argv[i]);
duke@1 318 } else if (arg.equals("-overview")) {
duke@1 319 oneArg(argv, i++);
duke@1 320 } else if (arg.equals("-doclet")) {
duke@1 321 i++; // handled in setDocletInvoker
duke@1 322 } else if (arg.equals("-docletpath")) {
duke@1 323 i++; // handled in setDocletInvoker
duke@1 324 } else if (arg.equals("-locale")) {
duke@1 325 if (i != 0)
duke@1 326 usageError("main.locale_first");
duke@1 327 oneArg(argv, i++);
duke@1 328 docLocale = argv[i];
jjg@584 329 } else if (arg.equals("-Xmaxerrs") || arg.equals("-Xmaxwarns")) {
jjg@584 330 oneArg(argv, i++);
jjg@584 331 if (compOpts.get(arg) != null) {
jjg@584 332 usageError("main.option.already.seen", arg);
jjg@584 333 }
jjg@584 334 compOpts.put(arg, argv[i]);
jjg@584 335 } else if (arg.equals("-X")) {
jjg@584 336 Xusage();
jjg@584 337 exit();
duke@1 338 } else if (arg.startsWith("-XD")) {
duke@1 339 String s = arg.substring("-XD".length());
duke@1 340 int eq = s.indexOf('=');
duke@1 341 String key = (eq < 0) ? s : s.substring(0, eq);
duke@1 342 String value = (eq < 0) ? s : s.substring(eq+1);
duke@1 343 compOpts.put(key, value);
duke@1 344 }
duke@1 345 // call doclet for its options
duke@1 346 // other arg starts with - is invalid
duke@1 347 else if ( arg.startsWith("-") ) {
duke@1 348 int optionLength;
duke@1 349 optionLength = docletInvoker.optionLength(arg);
duke@1 350 if (optionLength < 0) {
duke@1 351 // error already displayed
duke@1 352 exit();
duke@1 353 } else if (optionLength == 0) {
duke@1 354 // option not found
duke@1 355 usageError("main.invalid_flag", arg);
duke@1 356 } else {
duke@1 357 // doclet added option
duke@1 358 if ((i + optionLength) > argv.length) {
duke@1 359 usageError("main.requires_argument", arg);
duke@1 360 }
duke@1 361 ListBuffer<String> args = new ListBuffer<String>();
duke@1 362 for (int j = 0; j < optionLength-1; ++j) {
duke@1 363 args.append(argv[++i]);
duke@1 364 }
duke@1 365 setOption(arg, args.toList());
duke@1 366 }
duke@1 367 } else {
duke@1 368 javaNames.append(arg);
duke@1 369 }
duke@1 370 }
duke@1 371
duke@1 372 if (javaNames.isEmpty() && subPackages.isEmpty()) {
duke@1 373 usageError("main.No_packages_or_classes_specified");
duke@1 374 }
duke@1 375
duke@1 376 if (!docletInvoker.validOptions(options.toList())) {
duke@1 377 // error message already displayed
duke@1 378 exit();
duke@1 379 }
duke@1 380
duke@1 381 JavadocTool comp = JavadocTool.make0(context);
duke@1 382 if (comp == null) return false;
duke@1 383
duke@1 384 if (showAccess == null) {
duke@1 385 setFilter(defaultFilter);
duke@1 386 }
duke@1 387
duke@1 388 LanguageVersion languageVersion = docletInvoker.languageVersion();
duke@1 389 RootDocImpl root = comp.getRootDocImpl(
duke@1 390 docLocale, encoding, showAccess,
duke@1 391 javaNames.toList(), options.toList(), breakiterator,
duke@1 392 subPackages.toList(), excludedPackages.toList(),
duke@1 393 docClasses,
duke@1 394 // legacy?
duke@1 395 languageVersion == null || languageVersion == LanguageVersion.JAVA_1_1, quiet);
duke@1 396
duke@1 397 // pass off control to the doclet
duke@1 398 boolean ok = root != null;
duke@1 399 if (ok) ok = docletInvoker.start(root);
duke@1 400
jjg@912 401 Messager docletMessager = Messager.instance0(context);
jjg@912 402 messager.nwarnings += docletMessager.nwarnings;
jjg@912 403 messager.nerrors += docletMessager.nerrors;
jjg@912 404
duke@1 405 // We're done.
duke@1 406 if (compOpts.get("-verbose") != null) {
duke@1 407 tm = System.currentTimeMillis() - tm;
duke@1 408 messager.notice("main.done_in", Long.toString(tm));
duke@1 409 }
duke@1 410
duke@1 411 return ok;
duke@1 412 }
duke@1 413
duke@1 414 private void setDocletInvoker(String[] argv) {
duke@1 415 String docletClassName = null;
duke@1 416 String docletPath = null;
duke@1 417
duke@1 418 // Parse doclet specifying arguments
duke@1 419 for (int i = 0 ; i < argv.length ; i++) {
duke@1 420 String arg = argv[i];
duke@1 421 if (arg.equals("-doclet")) {
duke@1 422 oneArg(argv, i++);
duke@1 423 if (docletClassName != null) {
duke@1 424 usageError("main.more_than_one_doclet_specified_0_and_1",
duke@1 425 docletClassName, argv[i]);
duke@1 426 }
duke@1 427 docletClassName = argv[i];
duke@1 428 } else if (arg.equals("-docletpath")) {
duke@1 429 oneArg(argv, i++);
duke@1 430 if (docletPath == null) {
duke@1 431 docletPath = argv[i];
duke@1 432 } else {
duke@1 433 docletPath += File.pathSeparator + argv[i];
duke@1 434 }
duke@1 435 }
duke@1 436 }
duke@1 437
duke@1 438 if (docletClassName == null) {
duke@1 439 docletClassName = defaultDocletClassName;
duke@1 440 }
duke@1 441
duke@1 442 // attempt to find doclet
duke@1 443 docletInvoker = new DocletInvoker(messager,
jjg@129 444 docletClassName, docletPath,
jjg@129 445 docletParentClassLoader);
duke@1 446 }
duke@1 447
duke@1 448 private void setFilter(long filterBits) {
duke@1 449 if (showAccess != null) {
duke@1 450 messager.error(null, "main.incompatible.access.flags");
duke@1 451 usage();
duke@1 452 exit();
duke@1 453 }
duke@1 454 showAccess = new ModifierFilter(filterBits);
duke@1 455 }
duke@1 456
duke@1 457 /**
duke@1 458 * Set one arg option.
duke@1 459 * Error and exit if one argument is not provided.
duke@1 460 */
duke@1 461 private void oneArg(String[] args, int index) {
duke@1 462 if ((index + 1) < args.length) {
duke@1 463 setOption(args[index], args[index+1]);
duke@1 464 } else {
duke@1 465 usageError("main.requires_argument", args[index]);
duke@1 466 }
duke@1 467 }
duke@1 468
duke@1 469 private void usageError(String key) {
duke@1 470 messager.error(null, key);
duke@1 471 usage();
duke@1 472 exit();
duke@1 473 }
duke@1 474
duke@1 475 private void usageError(String key, String a1) {
duke@1 476 messager.error(null, key, a1);
duke@1 477 usage();
duke@1 478 exit();
duke@1 479 }
duke@1 480
duke@1 481 private void usageError(String key, String a1, String a2) {
duke@1 482 messager.error(null, key, a1, a2);
duke@1 483 usage();
duke@1 484 exit();
duke@1 485 }
duke@1 486
duke@1 487 /**
duke@1 488 * indicate an option with no arguments was given.
duke@1 489 */
duke@1 490 private void setOption(String opt) {
duke@1 491 String[] option = { opt };
duke@1 492 options.append(option);
duke@1 493 }
duke@1 494
duke@1 495 /**
duke@1 496 * indicate an option with one argument was given.
duke@1 497 */
duke@1 498 private void setOption(String opt, String argument) {
duke@1 499 String[] option = { opt, argument };
duke@1 500 options.append(option);
duke@1 501 }
duke@1 502
duke@1 503 /**
duke@1 504 * indicate an option with the specified list of arguments was given.
duke@1 505 */
duke@1 506 private void setOption(String opt, List<String> arguments) {
duke@1 507 String[] args = new String[arguments.length() + 1];
duke@1 508 int k = 0;
duke@1 509 args[k++] = opt;
duke@1 510 for (List<String> i = arguments; i.nonEmpty(); i=i.tail) {
duke@1 511 args[k++] = i.head;
duke@1 512 }
duke@1 513 options = options.append(args);
duke@1 514 }
duke@1 515
duke@1 516 }

mercurial