src/share/classes/com/sun/tools/javadoc/DocletInvoker.java

Thu, 02 Oct 2008 19:58:40 -0700

author
xdono
date
Thu, 02 Oct 2008 19:58:40 -0700
changeset 117
24a47c3062fe
parent 115
829dea15ff99
child 129
944790f83b57
permissions
-rw-r--r--

6754988: Update copyright year
Summary: Update for files that have been modified starting July 2008
Reviewed-by: ohair, tbell

     1 /*
     2  * Copyright 1998-2008 Sun Microsystems, Inc.  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.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.javadoc;
    28 import com.sun.javadoc.*;
    30 import static com.sun.javadoc.LanguageVersion.*;
    32 import com.sun.tools.javac.util.List;
    34 import java.net.*;
    35 import java.lang.OutOfMemoryError;
    36 import java.lang.reflect.Method;
    37 import java.lang.reflect.Modifier;
    38 import java.lang.reflect.InvocationTargetException;
    40 import java.io.File;
    41 import java.io.IOException;
    42 import java.util.StringTokenizer;
    44 /**
    45  * Class creates, controls and invokes doclets.
    46  * @author Neal Gafter (rewrite)
    47  */
    48 public class DocletInvoker {
    50     private final Class<?> docletClass;
    52     private final String docletClassName;
    54     private final ClassLoader appClassLoader;
    56     private final Messager messager;
    58     private static class DocletInvokeException extends Exception {
    59         private static final long serialVersionUID = 0;
    60     }
    62     private String appendPath(String path1, String path2) {
    63         if (path1 == null || path1.length() == 0) {
    64             return path2 == null ? "." : path2;
    65         } else if (path2 == null || path2.length() == 0) {
    66             return path1;
    67         } else {
    68             return path1  + File.pathSeparator + path2;
    69         }
    70     }
    72     public DocletInvoker(Messager messager,
    73                          String docletClassName, String docletPath) {
    74         this.messager = messager;
    75         this.docletClassName = docletClassName;
    77         // construct class loader
    78         String cpString = null;   // make sure env.class.path defaults to dot
    80         // do prepends to get correct ordering
    81         cpString = appendPath(System.getProperty("env.class.path"), cpString);
    82         cpString = appendPath(System.getProperty("java.class.path"), cpString);
    83         cpString = appendPath(docletPath, cpString);
    84         URL[] urls = pathToURLs(cpString);
    85         appClassLoader = new URLClassLoader(urls);
    87         // attempt to find doclet
    88         Class dc = null;
    89         try {
    90             dc = appClassLoader.loadClass(docletClassName);
    91         } catch (ClassNotFoundException exc) {
    92             messager.error(null, "main.doclet_class_not_found", docletClassName);
    93             messager.exit();
    94         }
    95         docletClass = dc;
    96     }
    98     /**
    99      * Generate documentation here.  Return true on success.
   100      */
   101     public boolean start(RootDoc root) {
   102         Object retVal;
   103         String methodName = "start";
   104         Class[] paramTypes = new Class[1];
   105         Object[] params = new Object[1];
   106         paramTypes[0] = RootDoc.class;
   107         params[0] = root;
   108         try {
   109             retVal = invoke(methodName, null, paramTypes, params);
   110         } catch (DocletInvokeException exc) {
   111             return false;
   112         }
   113         if (retVal instanceof Boolean) {
   114             return ((Boolean)retVal).booleanValue();
   115         } else {
   116             messager.error(null, "main.must_return_boolean",
   117                            docletClassName, methodName);
   118             return false;
   119         }
   120     }
   122     /**
   123      * Check for doclet added options here. Zero return means
   124      * option not known.  Positive value indicates number of
   125      * arguments to option.  Negative value means error occurred.
   126      */
   127     public int optionLength(String option) {
   128         Object retVal;
   129         String methodName = "optionLength";
   130         Class[] paramTypes = new Class[1];
   131         Object[] params = new Object[1];
   132         paramTypes[0] = option.getClass();
   133         params[0] = option;
   134         try {
   135             retVal = invoke(methodName, new Integer(0), paramTypes, params);
   136         } catch (DocletInvokeException exc) {
   137             return -1;
   138         }
   139         if (retVal instanceof Integer) {
   140             return ((Integer)retVal).intValue();
   141         } else {
   142             messager.error(null, "main.must_return_int",
   143                            docletClassName, methodName);
   144             return -1;
   145         }
   146     }
   148     /**
   149      * Let doclet check that all options are OK. Returning true means
   150      * options are OK.  If method does not exist, assume true.
   151      */
   152     public boolean validOptions(List<String[]> optlist) {
   153         Object retVal;
   154         String options[][] = optlist.toArray(new String[optlist.length()][]);
   155         String methodName = "validOptions";
   156         DocErrorReporter reporter = messager;
   157         Class[] paramTypes = new Class[2];
   158         Object[] params = new Object[2];
   159         paramTypes[0] = options.getClass();
   160         paramTypes[1] = DocErrorReporter.class;
   161         params[0] = options;
   162         params[1] = reporter;
   163         try {
   164             retVal = invoke(methodName, Boolean.TRUE, paramTypes, params);
   165         } catch (DocletInvokeException exc) {
   166             return false;
   167         }
   168         if (retVal instanceof Boolean) {
   169             return ((Boolean)retVal).booleanValue();
   170         } else {
   171             messager.error(null, "main.must_return_boolean",
   172                            docletClassName, methodName);
   173             return false;
   174         }
   175     }
   177     /**
   178      * Return the language version supported by this doclet.
   179      * If the method does not exist in the doclet, assume version 1.1.
   180      */
   181     public LanguageVersion languageVersion() {
   182         try {
   183             Object retVal;
   184             String methodName = "languageVersion";
   185             Class[] paramTypes = new Class[0];
   186             Object[] params = new Object[0];
   187             try {
   188                 retVal = invoke(methodName, JAVA_1_1, paramTypes, params);
   189             } catch (DocletInvokeException exc) {
   190                 return JAVA_1_1;
   191             }
   192             if (retVal instanceof LanguageVersion) {
   193                 return (LanguageVersion)retVal;
   194             } else {
   195                 messager.error(null, "main.must_return_languageversion",
   196                                docletClassName, methodName);
   197                 return JAVA_1_1;
   198             }
   199         } catch (NoClassDefFoundError ex) { // for boostrapping, no Enum class.
   200             return null;
   201         }
   202     }
   204     /**
   205      * Utility method for calling doclet functionality
   206      */
   207     private Object invoke(String methodName, Object returnValueIfNonExistent,
   208                           Class[] paramTypes, Object[] params)
   209         throws DocletInvokeException {
   210             Method meth;
   211             try {
   212                 meth = docletClass.getMethod(methodName, paramTypes);
   213             } catch (NoSuchMethodException exc) {
   214                 if (returnValueIfNonExistent == null) {
   215                     messager.error(null, "main.doclet_method_not_found",
   216                                    docletClassName, methodName);
   217                     throw new DocletInvokeException();
   218                 } else {
   219                     return returnValueIfNonExistent;
   220                 }
   221             } catch (SecurityException exc) {
   222                 messager.error(null, "main.doclet_method_not_accessible",
   223                                docletClassName, methodName);
   224                 throw new DocletInvokeException();
   225             }
   226             if (!Modifier.isStatic(meth.getModifiers())) {
   227                 messager.error(null, "main.doclet_method_must_be_static",
   228                                docletClassName, methodName);
   229                 throw new DocletInvokeException();
   230             }
   231             try {
   232                 Thread.currentThread().setContextClassLoader(appClassLoader);
   233                 return meth.invoke(null , params);
   234             } catch (IllegalArgumentException exc) {
   235                 messager.error(null, "main.internal_error_exception_thrown",
   236                                docletClassName, methodName, exc.toString());
   237                 throw new DocletInvokeException();
   238             } catch (IllegalAccessException exc) {
   239                 messager.error(null, "main.doclet_method_not_accessible",
   240                                docletClassName, methodName);
   241                 throw new DocletInvokeException();
   242             } catch (NullPointerException exc) {
   243                 messager.error(null, "main.internal_error_exception_thrown",
   244                                docletClassName, methodName, exc.toString());
   245                 throw new DocletInvokeException();
   246             } catch (InvocationTargetException exc) {
   247                 Throwable err = exc.getTargetException();
   248                 if (err instanceof java.lang.OutOfMemoryError) {
   249                     messager.error(null, "main.out.of.memory");
   250                 } else {
   251                 messager.error(null, "main.exception_thrown",
   252                                docletClassName, methodName, exc.toString());
   253                     exc.getTargetException().printStackTrace();
   254                 }
   255                 throw new DocletInvokeException();
   256             }
   257     }
   259     /**
   260      * Utility method for converting a search path string to an array
   261      * of directory and JAR file URLs.
   262      *
   263      * @param path the search path string
   264      * @return the resulting array of directory and JAR file URLs
   265      */
   266     static URL[] pathToURLs(String path) {
   267         StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
   268         URL[] urls = new URL[st.countTokens()];
   269         int count = 0;
   270         while (st.hasMoreTokens()) {
   271             URL url = fileToURL(new File(st.nextToken()));
   272             if (url != null) {
   273                 urls[count++] = url;
   274             }
   275         }
   276         if (urls.length != count) {
   277             URL[] tmp = new URL[count];
   278             System.arraycopy(urls, 0, tmp, 0, count);
   279             urls = tmp;
   280         }
   281         return urls;
   282     }
   284     /**
   285      * Returns the directory or JAR file URL corresponding to the specified
   286      * local file name.
   287      *
   288      * @param file the File object
   289      * @return the resulting directory or JAR file URL, or null if unknown
   290      */
   291     static URL fileToURL(File file) {
   292         String name;
   293         try {
   294             name = file.getCanonicalPath();
   295         } catch (IOException e) {
   296             name = file.getAbsolutePath();
   297         }
   298         name = name.replace(File.separatorChar, '/');
   299         if (!name.startsWith("/")) {
   300             name = "/" + name;
   301         }
   302         // If the file does not exist, then assume that it's a directory
   303         if (!file.isFile()) {
   304             name = name + "/";
   305         }
   306         try {
   307             return new URL("file", "", name);
   308         } catch (MalformedURLException e) {
   309             throw new IllegalArgumentException("file");
   310         }
   311     }
   312 }

mercurial