27 |
27 |
28 import java.io.File; |
28 import java.io.File; |
29 import java.io.FileNotFoundException; |
29 import java.io.FileNotFoundException; |
30 import java.io.IOException; |
30 import java.io.IOException; |
31 import java.io.PrintWriter; |
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; |
32 |
38 |
33 import com.sun.javadoc.*; |
39 import com.sun.javadoc.*; |
34 import com.sun.tools.javac.main.CommandLine; |
40 import com.sun.tools.javac.main.CommandLine; |
|
41 import com.sun.tools.javac.util.ClientCodeException; |
35 import com.sun.tools.javac.util.Context; |
42 import com.sun.tools.javac.util.Context; |
36 import com.sun.tools.javac.util.List; |
43 import com.sun.tools.javac.util.List; |
37 import com.sun.tools.javac.util.ListBuffer; |
44 import com.sun.tools.javac.util.ListBuffer; |
38 import com.sun.tools.javac.util.Log; |
45 import com.sun.tools.javac.util.Log; |
39 import com.sun.tools.javac.util.Options; |
46 import com.sun.tools.javac.util.Options; |
67 private long defaultFilter = PUBLIC | PROTECTED; |
74 private long defaultFilter = PUBLIC | PROTECTED; |
68 |
75 |
69 private final Messager messager; |
76 private final Messager messager; |
70 |
77 |
71 private DocletInvoker docletInvoker; |
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; |
72 |
85 |
73 Start(String programName, |
86 Start(String programName, |
74 PrintWriter errWriter, |
87 PrintWriter errWriter, |
75 PrintWriter warnWriter, |
88 PrintWriter warnWriter, |
76 PrintWriter noticeWriter, |
89 PrintWriter noticeWriter, |
119 } |
132 } |
120 |
133 |
121 public Start(Context context) { |
134 public Start(Context context) { |
122 context.getClass(); // null check |
135 context.getClass(); // null check |
123 this.context = context; |
136 this.context = context; |
|
137 apiMode = true; |
124 defaultDocletClassName = standardDocletClassName; |
138 defaultDocletClassName = standardDocletClassName; |
125 docletParentClassLoader = null; |
139 docletParentClassLoader = null; |
126 |
140 |
127 Log log = context.get(Log.logKey); |
141 Log log = context.get(Log.logKey); |
128 if (log instanceof Messager) |
142 if (log instanceof Messager) |
182 |
196 |
183 /** |
197 /** |
184 * Main program - external wrapper |
198 * Main program - external wrapper |
185 */ |
199 */ |
186 int begin(String... argv) { |
200 int begin(String... argv) { |
|
201 boolean ok = begin(null, argv, Collections.<JavaFileObject> emptySet()); |
|
202 return ok ? 0 : 1; |
|
203 } |
|
204 |
|
205 public boolean begin(Class<?> docletClass, Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) { |
|
206 Collection<String> opts = new ArrayList<String>(); |
|
207 for (String opt: options) opts.add(opt); |
|
208 return begin(docletClass, opts.toArray(new String[opts.size()]), fileObjects); |
|
209 } |
|
210 |
|
211 private boolean begin(Class<?> docletClass, String[] options, Iterable<? extends JavaFileObject> fileObjects) { |
187 boolean failed = false; |
212 boolean failed = false; |
188 |
213 |
189 try { |
214 try { |
190 failed = !parseAndExecute(argv); |
215 failed = !parseAndExecute(docletClass, options, fileObjects); |
191 } catch (Messager.ExitJavadoc exc) { |
216 } catch (Messager.ExitJavadoc exc) { |
192 // ignore, we just exit this way |
217 // ignore, we just exit this way |
193 } catch (OutOfMemoryError ee) { |
218 } catch (OutOfMemoryError ee) { |
194 messager.error(Messager.NOPOS, "main.out.of.memory"); |
219 messager.error(Messager.NOPOS, "main.out.of.memory"); |
195 failed = true; |
220 failed = true; |
|
221 } catch (ClientCodeException e) { |
|
222 // simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl |
|
223 throw e; |
196 } catch (Error ee) { |
224 } catch (Error ee) { |
197 ee.printStackTrace(System.err); |
225 ee.printStackTrace(System.err); |
198 messager.error(Messager.NOPOS, "main.fatal.error"); |
226 messager.error(Messager.NOPOS, "main.fatal.error"); |
199 failed = true; |
227 failed = true; |
200 } catch (Exception ee) { |
228 } catch (Exception ee) { |
205 messager.exitNotice(); |
233 messager.exitNotice(); |
206 messager.flush(); |
234 messager.flush(); |
207 } |
235 } |
208 failed |= messager.nerrors() > 0; |
236 failed |= messager.nerrors() > 0; |
209 failed |= rejectWarnings && messager.nwarnings() > 0; |
237 failed |= rejectWarnings && messager.nwarnings() > 0; |
210 return failed ? 1 : 0; |
238 return !failed; |
211 } |
239 } |
212 |
240 |
213 /** |
241 /** |
214 * Main program - internal |
242 * Main program - internal |
215 */ |
243 */ |
216 private boolean parseAndExecute(String... argv) throws IOException { |
244 private boolean parseAndExecute( |
|
245 Class<?> docletClass, |
|
246 String[] argv, |
|
247 Iterable<? extends JavaFileObject> fileObjects) throws IOException { |
217 long tm = System.currentTimeMillis(); |
248 long tm = System.currentTimeMillis(); |
218 |
249 |
219 ListBuffer<String> javaNames = new ListBuffer<String>(); |
250 ListBuffer<String> javaNames = new ListBuffer<String>(); |
220 |
251 |
221 // Preprocess @file arguments |
252 // Preprocess @file arguments |
227 } catch (IOException e) { |
258 } catch (IOException e) { |
228 e.printStackTrace(System.err); |
259 e.printStackTrace(System.err); |
229 exit(); |
260 exit(); |
230 } |
261 } |
231 |
262 |
232 setDocletInvoker(argv); |
263 |
|
264 JavaFileManager fileManager = context.get(JavaFileManager.class); |
|
265 setDocletInvoker(docletClass, fileManager, argv); |
233 |
266 |
234 compOpts = Options.instance(context); |
267 compOpts = Options.instance(context); |
235 |
268 |
236 // Parse arguments |
269 // Parse arguments |
237 for (int i = 0 ; i < argv.length ; i++) { |
270 for (int i = 0 ; i < argv.length ; i++) { |
285 javaNames.append(arg); |
318 javaNames.append(arg); |
286 } |
319 } |
287 } |
320 } |
288 compOpts.notifyListeners(); |
321 compOpts.notifyListeners(); |
289 |
322 |
290 if (javaNames.isEmpty() && subPackages.isEmpty()) { |
323 if (javaNames.isEmpty() && subPackages.isEmpty() && isEmpty(fileObjects)) { |
291 usageError("main.No_packages_or_classes_specified"); |
324 usageError("main.No_packages_or_classes_specified"); |
292 } |
325 } |
293 |
326 |
294 if (!docletInvoker.validOptions(options.toList())) { |
327 if (!docletInvoker.validOptions(options.toList())) { |
295 // error message already displayed |
328 // error message already displayed |
332 } |
366 } |
333 |
367 |
334 return ok; |
368 return ok; |
335 } |
369 } |
336 |
370 |
337 private void setDocletInvoker(String[] argv) { |
371 private <T> boolean isEmpty(Iterable<T> iter) { |
|
372 return !iter.iterator().hasNext(); |
|
373 } |
|
374 |
|
375 /** |
|
376 * Init the doclet invoker. |
|
377 * The doclet class may be given explicitly, or via the -doclet option in |
|
378 * argv. |
|
379 * If the doclet class is not given explicitly, it will be loaded from |
|
380 * the file manager's DOCLET_PATH location, if available, or via the |
|
381 * -doclet path option in argv. |
|
382 * @param docletClass The doclet class. May be null. |
|
383 * @param fileManager The file manager used to get the class loader to load |
|
384 * the doclet class if required. May be null. |
|
385 * @param argv Args containing -doclet and -docletpath, in case they are required. |
|
386 */ |
|
387 private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) { |
|
388 if (docletClass != null) { |
|
389 docletInvoker = new DocletInvoker(messager, docletClass, apiMode); |
|
390 // TODO, check no -doclet, -docletpath |
|
391 return; |
|
392 } |
|
393 |
338 String docletClassName = null; |
394 String docletClassName = null; |
339 String docletPath = null; |
395 String docletPath = null; |
340 |
396 |
341 // Parse doclet specifying arguments |
397 // Parse doclet specifying arguments |
342 for (int i = 0 ; i < argv.length ; i++) { |
398 for (int i = 0 ; i < argv.length ; i++) { |
343 String arg = argv[i]; |
399 String arg = argv[i]; |
344 if (arg.equals("-doclet")) { |
400 if (arg.equals(ToolOption.DOCLET.opt)) { |
345 oneArg(argv, i++); |
401 oneArg(argv, i++); |
346 if (docletClassName != null) { |
402 if (docletClassName != null) { |
347 usageError("main.more_than_one_doclet_specified_0_and_1", |
403 usageError("main.more_than_one_doclet_specified_0_and_1", |
348 docletClassName, argv[i]); |
404 docletClassName, argv[i]); |
349 } |
405 } |
350 docletClassName = argv[i]; |
406 docletClassName = argv[i]; |
351 } else if (arg.equals("-docletpath")) { |
407 } else if (arg.equals(ToolOption.DOCLETPATH.opt)) { |
352 oneArg(argv, i++); |
408 oneArg(argv, i++); |
353 if (docletPath == null) { |
409 if (docletPath == null) { |
354 docletPath = argv[i]; |
410 docletPath = argv[i]; |
355 } else { |
411 } else { |
356 docletPath += File.pathSeparator + argv[i]; |
412 docletPath += File.pathSeparator + argv[i]; |
361 if (docletClassName == null) { |
417 if (docletClassName == null) { |
362 docletClassName = defaultDocletClassName; |
418 docletClassName = defaultDocletClassName; |
363 } |
419 } |
364 |
420 |
365 // attempt to find doclet |
421 // attempt to find doclet |
366 docletInvoker = new DocletInvoker(messager, |
422 docletInvoker = new DocletInvoker(messager, fileManager, |
367 docletClassName, docletPath, |
423 docletClassName, docletPath, |
368 docletParentClassLoader); |
424 docletParentClassLoader, |
|
425 apiMode); |
369 } |
426 } |
370 |
427 |
371 /** |
428 /** |
372 * Set one arg option. |
429 * Set one arg option. |
373 * Error and exit if one argument is not provided. |
430 * Error and exit if one argument is not provided. |