Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/src/share/classes/com/sun/tools/javadoc/Start.java
38899 views
1
/*
2
* Copyright (c) 1997, 2013, 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
*/
25
26
package com.sun.tools.javadoc;
27
28
import java.io.File;
29
import java.io.FileNotFoundException;
30
import java.io.IOException;
31
import java.io.PrintWriter;
32
import java.util.ArrayList;
33
import java.util.Collection;
34
import java.util.Collections;
35
36
import javax.tools.JavaFileManager;
37
import javax.tools.JavaFileObject;
38
39
import com.sun.javadoc.*;
40
import com.sun.tools.javac.main.CommandLine;
41
import com.sun.tools.javac.util.ClientCodeException;
42
import com.sun.tools.javac.util.Context;
43
import com.sun.tools.javac.util.List;
44
import com.sun.tools.javac.util.ListBuffer;
45
import com.sun.tools.javac.util.Log;
46
import com.sun.tools.javac.util.Options;
47
import static com.sun.tools.javac.code.Flags.*;
48
49
/**
50
* Main program of Javadoc.
51
* Previously named "Main".
52
*
53
* <p><b>This is NOT part of any supported API.
54
* If you write code that depends on this, you do so at your own risk.
55
* This code and its internal interfaces are subject to change or
56
* deletion without notice.</b>
57
*
58
* @since 1.2
59
* @author Robert Field
60
* @author Neal Gafter (rewrite)
61
*/
62
public class Start extends ToolOption.Helper {
63
/** Context for this invocation. */
64
private final Context context;
65
66
private final String defaultDocletClassName;
67
private final ClassLoader docletParentClassLoader;
68
69
private static final String javadocName = "javadoc";
70
71
private static final String standardDocletClassName =
72
"com.sun.tools.doclets.standard.Standard";
73
74
private long defaultFilter = PUBLIC | PROTECTED;
75
76
private final Messager messager;
77
78
private DocletInvoker docletInvoker;
79
80
/**
81
* In API mode, exceptions thrown while calling the doclet are
82
* propagated using ClientCodeException.
83
*/
84
private boolean apiMode;
85
86
Start(String programName,
87
PrintWriter errWriter,
88
PrintWriter warnWriter,
89
PrintWriter noticeWriter,
90
String defaultDocletClassName) {
91
this(programName, errWriter, warnWriter, noticeWriter, defaultDocletClassName, null);
92
}
93
94
Start(String programName,
95
PrintWriter errWriter,
96
PrintWriter warnWriter,
97
PrintWriter noticeWriter,
98
String defaultDocletClassName,
99
ClassLoader docletParentClassLoader) {
100
context = new Context();
101
messager = new Messager(context, programName, errWriter, warnWriter, noticeWriter);
102
this.defaultDocletClassName = defaultDocletClassName;
103
this.docletParentClassLoader = docletParentClassLoader;
104
}
105
106
Start(String programName, String defaultDocletClassName) {
107
this(programName, defaultDocletClassName, null);
108
}
109
110
Start(String programName, String defaultDocletClassName,
111
ClassLoader docletParentClassLoader) {
112
context = new Context();
113
messager = new Messager(context, programName);
114
this.defaultDocletClassName = defaultDocletClassName;
115
this.docletParentClassLoader = docletParentClassLoader;
116
}
117
118
Start(String programName, ClassLoader docletParentClassLoader) {
119
this(programName, standardDocletClassName, docletParentClassLoader);
120
}
121
122
Start(String programName) {
123
this(programName, standardDocletClassName);
124
}
125
126
Start(ClassLoader docletParentClassLoader) {
127
this(javadocName, docletParentClassLoader);
128
}
129
130
Start() {
131
this(javadocName);
132
}
133
134
public Start(Context context) {
135
context.getClass(); // null check
136
this.context = context;
137
apiMode = true;
138
defaultDocletClassName = standardDocletClassName;
139
docletParentClassLoader = null;
140
141
Log log = context.get(Log.logKey);
142
if (log instanceof Messager)
143
messager = (Messager) log;
144
else {
145
PrintWriter out = context.get(Log.outKey);
146
messager = (out == null) ? new Messager(context, javadocName)
147
: new Messager(context, javadocName, out, out, out);
148
}
149
}
150
151
/**
152
* Usage
153
*/
154
@Override
155
void usage() {
156
usage(true);
157
}
158
159
void usage(boolean exit) {
160
usage("main.usage", "-help", null, exit);
161
}
162
163
@Override
164
void Xusage() {
165
Xusage(true);
166
}
167
168
void Xusage(boolean exit) {
169
usage("main.Xusage", "-X", "main.Xusage.foot", exit);
170
}
171
172
private void usage(String main, String doclet, String foot, boolean exit) {
173
// RFE: it would be better to replace the following with code to
174
// write a header, then help for each option, then a footer.
175
messager.notice(main);
176
177
// let doclet print usage information (does nothing on error)
178
if (docletInvoker != null) {
179
// RFE: this is a pretty bad way to get the doclet to show
180
// help info. Moreover, the output appears on stdout,
181
// and <i>not</i> on any of the standard streams passed
182
// to javadoc, and in particular, not to the noticeWriter
183
// But, to fix this, we need to fix the Doclet API.
184
docletInvoker.optionLength(doclet);
185
}
186
187
if (foot != null)
188
messager.notice(foot);
189
190
if (exit) exit();
191
}
192
193
/**
194
* Exit
195
*/
196
private void exit() {
197
messager.exit();
198
}
199
200
201
/**
202
* Main program - external wrapper
203
*/
204
int begin(String... argv) {
205
boolean ok = begin(null, argv, Collections.<JavaFileObject> emptySet());
206
return ok ? 0 : 1;
207
}
208
209
public boolean begin(Class<?> docletClass, Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) {
210
Collection<String> opts = new ArrayList<String>();
211
for (String opt: options) opts.add(opt);
212
return begin(docletClass, opts.toArray(new String[opts.size()]), fileObjects);
213
}
214
215
private boolean begin(Class<?> docletClass, String[] options, Iterable<? extends JavaFileObject> fileObjects) {
216
boolean failed = false;
217
218
try {
219
failed = !parseAndExecute(docletClass, options, fileObjects);
220
} catch (Messager.ExitJavadoc exc) {
221
// ignore, we just exit this way
222
} catch (OutOfMemoryError ee) {
223
messager.error(Messager.NOPOS, "main.out.of.memory");
224
failed = true;
225
} catch (ClientCodeException e) {
226
// simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl
227
throw e;
228
} catch (Error ee) {
229
ee.printStackTrace(System.err);
230
messager.error(Messager.NOPOS, "main.fatal.error");
231
failed = true;
232
} catch (Exception ee) {
233
ee.printStackTrace(System.err);
234
messager.error(Messager.NOPOS, "main.fatal.exception");
235
failed = true;
236
} finally {
237
messager.exitNotice();
238
messager.flush();
239
}
240
failed |= messager.nerrors() > 0;
241
failed |= rejectWarnings && messager.nwarnings() > 0;
242
return !failed;
243
}
244
245
/**
246
* Main program - internal
247
*/
248
private boolean parseAndExecute(
249
Class<?> docletClass,
250
String[] argv,
251
Iterable<? extends JavaFileObject> fileObjects) throws IOException {
252
long tm = System.currentTimeMillis();
253
254
ListBuffer<String> javaNames = new ListBuffer<String>();
255
256
// Preprocess @file arguments
257
try {
258
argv = CommandLine.parse(argv);
259
} catch (FileNotFoundException e) {
260
messager.error(Messager.NOPOS, "main.cant.read", e.getMessage());
261
exit();
262
} catch (IOException e) {
263
e.printStackTrace(System.err);
264
exit();
265
}
266
267
268
JavaFileManager fileManager = context.get(JavaFileManager.class);
269
setDocletInvoker(docletClass, fileManager, argv);
270
271
compOpts = Options.instance(context);
272
// Make sure no obsolete source/target messages are reported
273
compOpts.put("-Xlint:-options", "-Xlint:-options");
274
275
// Parse arguments
276
for (int i = 0 ; i < argv.length ; i++) {
277
String arg = argv[i];
278
279
ToolOption o = ToolOption.get(arg);
280
if (o != null) {
281
// hack: this restriction should be removed
282
if (o == ToolOption.LOCALE && i > 0)
283
usageError("main.locale_first");
284
285
if (o.hasArg) {
286
oneArg(argv, i++);
287
o.process(this, argv[i]);
288
} else {
289
setOption(arg);
290
o.process(this);
291
}
292
293
} else if (arg.startsWith("-XD")) {
294
// hidden javac options
295
String s = arg.substring("-XD".length());
296
int eq = s.indexOf('=');
297
String key = (eq < 0) ? s : s.substring(0, eq);
298
String value = (eq < 0) ? s : s.substring(eq+1);
299
compOpts.put(key, value);
300
}
301
// call doclet for its options
302
// other arg starts with - is invalid
303
else if (arg.startsWith("-")) {
304
int optionLength;
305
optionLength = docletInvoker.optionLength(arg);
306
if (optionLength < 0) {
307
// error already displayed
308
exit();
309
} else if (optionLength == 0) {
310
// option not found
311
usageError("main.invalid_flag", arg);
312
} else {
313
// doclet added option
314
if ((i + optionLength) > argv.length) {
315
usageError("main.requires_argument", arg);
316
}
317
ListBuffer<String> args = new ListBuffer<String>();
318
for (int j = 0; j < optionLength-1; ++j) {
319
args.append(argv[++i]);
320
}
321
setOption(arg, args.toList());
322
}
323
} else {
324
javaNames.append(arg);
325
}
326
}
327
compOpts.notifyListeners();
328
329
if (javaNames.isEmpty() && subPackages.isEmpty() && isEmpty(fileObjects)) {
330
usageError("main.No_packages_or_classes_specified");
331
}
332
333
if (!docletInvoker.validOptions(options.toList())) {
334
// error message already displayed
335
exit();
336
}
337
338
JavadocTool comp = JavadocTool.make0(context);
339
if (comp == null) return false;
340
341
if (showAccess == null) {
342
setFilter(defaultFilter);
343
}
344
345
LanguageVersion languageVersion = docletInvoker.languageVersion();
346
RootDocImpl root = comp.getRootDocImpl(
347
docLocale,
348
encoding,
349
showAccess,
350
javaNames.toList(),
351
options.toList(),
352
fileObjects,
353
breakiterator,
354
subPackages.toList(),
355
excludedPackages.toList(),
356
docClasses,
357
// legacy?
358
languageVersion == null || languageVersion == LanguageVersion.JAVA_1_1,
359
quiet);
360
361
// release resources
362
comp = null;
363
364
// pass off control to the doclet
365
boolean ok = root != null;
366
if (ok) ok = docletInvoker.start(root);
367
368
// We're done.
369
if (compOpts.get("-verbose") != null) {
370
tm = System.currentTimeMillis() - tm;
371
messager.notice("main.done_in", Long.toString(tm));
372
}
373
374
return ok;
375
}
376
377
private <T> boolean isEmpty(Iterable<T> iter) {
378
return !iter.iterator().hasNext();
379
}
380
381
/**
382
* Init the doclet invoker.
383
* The doclet class may be given explicitly, or via the -doclet option in
384
* argv.
385
* If the doclet class is not given explicitly, it will be loaded from
386
* the file manager's DOCLET_PATH location, if available, or via the
387
* -doclet path option in argv.
388
* @param docletClass The doclet class. May be null.
389
* @param fileManager The file manager used to get the class loader to load
390
* the doclet class if required. May be null.
391
* @param argv Args containing -doclet and -docletpath, in case they are required.
392
*/
393
private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) {
394
if (docletClass != null) {
395
docletInvoker = new DocletInvoker(messager, docletClass, apiMode);
396
// TODO, check no -doclet, -docletpath
397
return;
398
}
399
400
String docletClassName = null;
401
String docletPath = null;
402
403
// Parse doclet specifying arguments
404
for (int i = 0 ; i < argv.length ; i++) {
405
String arg = argv[i];
406
if (arg.equals(ToolOption.DOCLET.opt)) {
407
oneArg(argv, i++);
408
if (docletClassName != null) {
409
usageError("main.more_than_one_doclet_specified_0_and_1",
410
docletClassName, argv[i]);
411
}
412
docletClassName = argv[i];
413
} else if (arg.equals(ToolOption.DOCLETPATH.opt)) {
414
oneArg(argv, i++);
415
if (docletPath == null) {
416
docletPath = argv[i];
417
} else {
418
docletPath += File.pathSeparator + argv[i];
419
}
420
}
421
}
422
423
if (docletClassName == null) {
424
docletClassName = defaultDocletClassName;
425
}
426
427
// attempt to find doclet
428
docletInvoker = new DocletInvoker(messager, fileManager,
429
docletClassName, docletPath,
430
docletParentClassLoader,
431
apiMode);
432
}
433
434
/**
435
* Set one arg option.
436
* Error and exit if one argument is not provided.
437
*/
438
private void oneArg(String[] args, int index) {
439
if ((index + 1) < args.length) {
440
setOption(args[index], args[index+1]);
441
} else {
442
usageError("main.requires_argument", args[index]);
443
}
444
}
445
446
@Override
447
void usageError(String key, Object... args) {
448
messager.error(Messager.NOPOS, key, args);
449
usage(true);
450
}
451
452
/**
453
* indicate an option with no arguments was given.
454
*/
455
private void setOption(String opt) {
456
String[] option = { opt };
457
options.append(option);
458
}
459
460
/**
461
* indicate an option with one argument was given.
462
*/
463
private void setOption(String opt, String argument) {
464
String[] option = { opt, argument };
465
options.append(option);
466
}
467
468
/**
469
* indicate an option with the specified list of arguments was given.
470
*/
471
private void setOption(String opt, List<String> arguments) {
472
String[] args = new String[arguments.length() + 1];
473
int k = 0;
474
args[k++] = opt;
475
for (List<String> i = arguments; i.nonEmpty(); i=i.tail) {
476
args[k++] = i.head;
477
}
478
options.append(args);
479
}
480
}
481
482