langtools/src/share/classes/com/sun/tools/javadoc/Start.java
changeset 14545 2e7bab0639b8
parent 14543 43edeaf6d0a9
child 18005 598e2e068668
equal deleted inserted replaced
14544:d71d992cb905 14545:2e7bab0639b8
    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
   308                 docLocale,
   341                 docLocale,
   309                 encoding,
   342                 encoding,
   310                 showAccess,
   343                 showAccess,
   311                 javaNames.toList(),
   344                 javaNames.toList(),
   312                 options.toList(),
   345                 options.toList(),
       
   346                 fileObjects,
   313                 breakiterator,
   347                 breakiterator,
   314                 subPackages.toList(),
   348                 subPackages.toList(),
   315                 excludedPackages.toList(),
   349                 excludedPackages.toList(),
   316                 docClasses,
   350                 docClasses,
   317                 // legacy?
   351                 // legacy?
   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.