Thu, 30 Jun 2011 14:33:45 -0700
7059905: (javadoc) promote method visibility for netbeans usage
Reviewed-by: jjg, bpatel
1 /*
2 * Copyright (c) 1997, 2011, 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 com.sun.javadoc.*;
30 import com.sun.tools.javac.main.CommandLine;
31 import com.sun.tools.javac.util.Context;
32 import com.sun.tools.javac.util.List;
33 import com.sun.tools.javac.util.ListBuffer;
34 import com.sun.tools.javac.util.Options;
36 import java.io.IOException;
37 import java.io.File;
38 import java.io.FileNotFoundException;
39 import java.io.PrintWriter;
41 import java.util.StringTokenizer;
43 import static com.sun.tools.javac.code.Flags.*;
45 /**
46 * Main program of Javadoc.
47 * Previously named "Main".
48 *
49 * @since 1.2
50 * @author Robert Field
51 * @author Neal Gafter (rewrite)
52 */
53 class Start {
55 private final String defaultDocletClassName;
56 private final ClassLoader docletParentClassLoader;
58 private static final String javadocName = "javadoc";
60 private static final String standardDocletClassName =
61 "com.sun.tools.doclets.standard.Standard";
63 private ListBuffer<String[]> options = new ListBuffer<String[]>();
65 private ModifierFilter showAccess = null;
67 private long defaultFilter = PUBLIC | PROTECTED;
69 private Messager messager;
71 String docLocale = "";
73 boolean breakiterator = false;
74 boolean quiet = false;
75 String encoding = null;
77 private DocletInvoker docletInvoker;
79 private static final int F_VERBOSE = 1 << 0;
80 private static final int F_WARNINGS = 1 << 2;
82 /* Treat warnings as errors. */
83 private boolean rejectWarnings = false;
85 Start(String programName,
86 PrintWriter errWriter,
87 PrintWriter warnWriter,
88 PrintWriter noticeWriter,
89 String defaultDocletClassName) {
90 this(programName, errWriter, warnWriter, noticeWriter, defaultDocletClassName, null);
91 }
93 Start(String programName,
94 PrintWriter errWriter,
95 PrintWriter warnWriter,
96 PrintWriter noticeWriter,
97 String defaultDocletClassName,
98 ClassLoader docletParentClassLoader) {
99 Context tempContext = new Context(); // interim context until option decoding completed
100 messager = new Messager(tempContext, programName, errWriter, warnWriter, noticeWriter);
101 this.defaultDocletClassName = defaultDocletClassName;
102 this.docletParentClassLoader = docletParentClassLoader;
103 }
105 Start(String programName, String defaultDocletClassName) {
106 this(programName, defaultDocletClassName, null);
107 }
109 Start(String programName, String defaultDocletClassName,
110 ClassLoader docletParentClassLoader) {
111 Context tempContext = new Context(); // interim context until option decoding completed
112 messager = new Messager(tempContext, programName);
113 this.defaultDocletClassName = defaultDocletClassName;
114 this.docletParentClassLoader = docletParentClassLoader;
115 }
117 Start(String programName, ClassLoader docletParentClassLoader) {
118 this(programName, standardDocletClassName, docletParentClassLoader);
119 }
121 Start(String programName) {
122 this(programName, standardDocletClassName);
123 }
125 Start(ClassLoader docletParentClassLoader) {
126 this(javadocName, docletParentClassLoader);
127 }
129 Start() {
130 this(javadocName);
131 }
133 /**
134 * Usage
135 */
136 private void usage() {
137 messager.notice("main.usage");
139 // let doclet print usage information (does nothing on error)
140 if (docletInvoker != null) {
141 docletInvoker.optionLength("-help");
142 }
143 }
145 /**
146 * Usage
147 */
148 private void Xusage() {
149 messager.notice("main.Xusage");
150 }
152 /**
153 * Exit
154 */
155 private void exit() {
156 messager.exit();
157 }
160 /**
161 * Main program - external wrapper
162 */
163 int begin(String... argv) {
164 boolean failed = false;
166 try {
167 failed = !parseAndExecute(argv);
168 } catch(Messager.ExitJavadoc exc) {
169 // ignore, we just exit this way
170 } catch (OutOfMemoryError ee) {
171 messager.error(null, "main.out.of.memory");
172 failed = true;
173 } catch (Error ee) {
174 ee.printStackTrace();
175 messager.error(null, "main.fatal.error");
176 failed = true;
177 } catch (Exception ee) {
178 ee.printStackTrace();
179 messager.error(null, "main.fatal.exception");
180 failed = true;
181 } finally {
182 messager.exitNotice();
183 messager.flush();
184 }
185 failed |= messager.nerrors() > 0;
186 failed |= rejectWarnings && messager.nwarnings() > 0;
187 return failed ? 1 : 0;
188 }
190 private void addToList(ListBuffer<String> list, String str){
191 StringTokenizer st = new StringTokenizer(str, ":");
192 String current;
193 while(st.hasMoreTokens()){
194 current = st.nextToken();
195 list.append(current);
196 }
197 }
199 /**
200 * Main program - internal
201 */
202 private boolean parseAndExecute(String... argv) throws IOException {
203 long tm = System.currentTimeMillis();
205 ListBuffer<String> javaNames = new ListBuffer<String>();
207 // Preprocess @file arguments
208 try {
209 argv = CommandLine.parse(argv);
210 } catch (FileNotFoundException e) {
211 messager.error(null, "main.cant.read", e.getMessage());
212 exit();
213 } catch (IOException e) {
214 e.printStackTrace();
215 exit();
216 }
218 setDocletInvoker(argv);
219 ListBuffer<String> subPackages = new ListBuffer<String>();
220 ListBuffer<String> excludedPackages = new ListBuffer<String>();
222 Context context = new Context();
223 // Setup a new Messager, using the same initial parameters as the
224 // existing Messager, except that this one will be able to use any
225 // options that may be set up below.
226 Messager.preRegister(context,
227 messager.programName,
228 messager.errWriter, messager.warnWriter, messager.noticeWriter);
230 Options compOpts = Options.instance(context);
231 boolean docClasses = false;
233 // Parse arguments
234 for (int i = 0 ; i < argv.length ; i++) {
235 String arg = argv[i];
236 if (arg.equals("-subpackages")) {
237 oneArg(argv, i++);
238 addToList(subPackages, argv[i]);
239 } else if (arg.equals("-exclude")){
240 oneArg(argv, i++);
241 addToList(excludedPackages, argv[i]);
242 } else if (arg.equals("-verbose")) {
243 setOption(arg);
244 compOpts.put("-verbose", "");
245 } else if (arg.equals("-encoding")) {
246 oneArg(argv, i++);
247 encoding = argv[i];
248 compOpts.put("-encoding", argv[i]);
249 } else if (arg.equals("-breakiterator")) {
250 breakiterator = true;
251 setOption("-breakiterator");
252 } else if (arg.equals("-quiet")) {
253 quiet = true;
254 setOption("-quiet");
255 } else if (arg.equals("-help")) {
256 usage();
257 exit();
258 } else if (arg.equals("-Xclasses")) {
259 setOption(arg);
260 docClasses = true;
261 } else if (arg.equals("-Xwerror")) {
262 setOption(arg);
263 rejectWarnings = true;
264 } else if (arg.equals("-private")) {
265 setOption(arg);
266 setFilter(ModifierFilter.ALL_ACCESS);
267 } else if (arg.equals("-package")) {
268 setOption(arg);
269 setFilter(PUBLIC | PROTECTED |
270 ModifierFilter.PACKAGE );
271 } else if (arg.equals("-protected")) {
272 setOption(arg);
273 setFilter(PUBLIC | PROTECTED );
274 } else if (arg.equals("-public")) {
275 setOption(arg);
276 setFilter(PUBLIC);
277 } else if (arg.equals("-source")) {
278 oneArg(argv, i++);
279 if (compOpts.get("-source") != null) {
280 usageError("main.option.already.seen", arg);
281 }
282 compOpts.put("-source", argv[i]);
283 } else if (arg.equals("-prompt")) {
284 compOpts.put("-prompt", "-prompt");
285 messager.promptOnError = true;
286 } else if (arg.equals("-sourcepath")) {
287 oneArg(argv, i++);
288 if (compOpts.get("-sourcepath") != null) {
289 usageError("main.option.already.seen", arg);
290 }
291 compOpts.put("-sourcepath", argv[i]);
292 } else if (arg.equals("-classpath")) {
293 oneArg(argv, i++);
294 if (compOpts.get("-classpath") != null) {
295 usageError("main.option.already.seen", arg);
296 }
297 compOpts.put("-classpath", argv[i]);
298 } else if (arg.equals("-sysclasspath")) {
299 oneArg(argv, i++);
300 if (compOpts.get("-bootclasspath") != null) {
301 usageError("main.option.already.seen", arg);
302 }
303 compOpts.put("-bootclasspath", argv[i]);
304 } else if (arg.equals("-bootclasspath")) {
305 oneArg(argv, i++);
306 if (compOpts.get("-bootclasspath") != null) {
307 usageError("main.option.already.seen", arg);
308 }
309 compOpts.put("-bootclasspath", argv[i]);
310 } else if (arg.equals("-extdirs")) {
311 oneArg(argv, i++);
312 if (compOpts.get("-extdirs") != null) {
313 usageError("main.option.already.seen", arg);
314 }
315 compOpts.put("-extdirs", argv[i]);
316 } else if (arg.equals("-overview")) {
317 oneArg(argv, i++);
318 } else if (arg.equals("-doclet")) {
319 i++; // handled in setDocletInvoker
320 } else if (arg.equals("-docletpath")) {
321 i++; // handled in setDocletInvoker
322 } else if (arg.equals("-locale")) {
323 if (i != 0)
324 usageError("main.locale_first");
325 oneArg(argv, i++);
326 docLocale = argv[i];
327 } else if (arg.equals("-Xmaxerrs") || arg.equals("-Xmaxwarns")) {
328 oneArg(argv, i++);
329 if (compOpts.get(arg) != null) {
330 usageError("main.option.already.seen", arg);
331 }
332 compOpts.put(arg, argv[i]);
333 } else if (arg.equals("-X")) {
334 Xusage();
335 exit();
336 } else if (arg.startsWith("-XD")) {
337 String s = arg.substring("-XD".length());
338 int eq = s.indexOf('=');
339 String key = (eq < 0) ? s : s.substring(0, eq);
340 String value = (eq < 0) ? s : s.substring(eq+1);
341 compOpts.put(key, value);
342 }
343 // call doclet for its options
344 // other arg starts with - is invalid
345 else if ( arg.startsWith("-") ) {
346 int optionLength;
347 optionLength = docletInvoker.optionLength(arg);
348 if (optionLength < 0) {
349 // error already displayed
350 exit();
351 } else if (optionLength == 0) {
352 // option not found
353 usageError("main.invalid_flag", arg);
354 } else {
355 // doclet added option
356 if ((i + optionLength) > argv.length) {
357 usageError("main.requires_argument", arg);
358 }
359 ListBuffer<String> args = new ListBuffer<String>();
360 for (int j = 0; j < optionLength-1; ++j) {
361 args.append(argv[++i]);
362 }
363 setOption(arg, args.toList());
364 }
365 } else {
366 javaNames.append(arg);
367 }
368 }
370 if (javaNames.isEmpty() && subPackages.isEmpty()) {
371 usageError("main.No_packages_or_classes_specified");
372 }
374 if (!docletInvoker.validOptions(options.toList())) {
375 // error message already displayed
376 exit();
377 }
379 JavadocTool comp = JavadocTool.make0(context);
380 if (comp == null) return false;
382 if (showAccess == null) {
383 setFilter(defaultFilter);
384 }
386 LanguageVersion languageVersion = docletInvoker.languageVersion();
387 RootDocImpl root = comp.getRootDocImpl(
388 docLocale, encoding, showAccess,
389 javaNames.toList(), options.toList(), breakiterator,
390 subPackages.toList(), excludedPackages.toList(),
391 docClasses,
392 // legacy?
393 languageVersion == null || languageVersion == LanguageVersion.JAVA_1_1, quiet);
395 // pass off control to the doclet
396 boolean ok = root != null;
397 if (ok) ok = docletInvoker.start(root);
399 Messager docletMessager = Messager.instance0(context);
400 messager.nwarnings += docletMessager.nwarnings;
401 messager.nerrors += docletMessager.nerrors;
403 // We're done.
404 if (compOpts.get("-verbose") != null) {
405 tm = System.currentTimeMillis() - tm;
406 messager.notice("main.done_in", Long.toString(tm));
407 }
409 return ok;
410 }
412 private void setDocletInvoker(String[] argv) {
413 String docletClassName = null;
414 String docletPath = null;
416 // Parse doclet specifying arguments
417 for (int i = 0 ; i < argv.length ; i++) {
418 String arg = argv[i];
419 if (arg.equals("-doclet")) {
420 oneArg(argv, i++);
421 if (docletClassName != null) {
422 usageError("main.more_than_one_doclet_specified_0_and_1",
423 docletClassName, argv[i]);
424 }
425 docletClassName = argv[i];
426 } else if (arg.equals("-docletpath")) {
427 oneArg(argv, i++);
428 if (docletPath == null) {
429 docletPath = argv[i];
430 } else {
431 docletPath += File.pathSeparator + argv[i];
432 }
433 }
434 }
436 if (docletClassName == null) {
437 docletClassName = defaultDocletClassName;
438 }
440 // attempt to find doclet
441 docletInvoker = new DocletInvoker(messager,
442 docletClassName, docletPath,
443 docletParentClassLoader);
444 }
446 private void setFilter(long filterBits) {
447 if (showAccess != null) {
448 messager.error(null, "main.incompatible.access.flags");
449 usage();
450 exit();
451 }
452 showAccess = new ModifierFilter(filterBits);
453 }
455 /**
456 * Set one arg option.
457 * Error and exit if one argument is not provided.
458 */
459 private void oneArg(String[] args, int index) {
460 if ((index + 1) < args.length) {
461 setOption(args[index], args[index+1]);
462 } else {
463 usageError("main.requires_argument", args[index]);
464 }
465 }
467 private void usageError(String key) {
468 messager.error(null, key);
469 usage();
470 exit();
471 }
473 private void usageError(String key, String a1) {
474 messager.error(null, key, a1);
475 usage();
476 exit();
477 }
479 private void usageError(String key, String a1, String a2) {
480 messager.error(null, key, a1, a2);
481 usage();
482 exit();
483 }
485 /**
486 * indicate an option with no arguments was given.
487 */
488 private void setOption(String opt) {
489 String[] option = { opt };
490 options.append(option);
491 }
493 /**
494 * indicate an option with one argument was given.
495 */
496 private void setOption(String opt, String argument) {
497 String[] option = { opt, argument };
498 options.append(option);
499 }
501 /**
502 * indicate an option with the specified list of arguments was given.
503 */
504 private void setOption(String opt, List<String> arguments) {
505 String[] args = new String[arguments.length() + 1];
506 int k = 0;
507 args[k++] = opt;
508 for (List<String> i = arguments; i.nonEmpty(); i=i.tail) {
509 args[k++] = i.head;
510 }
511 options = options.append(args);
512 }
514 }