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