6176978: current Javadoc's invocation and extension (Doclet) mechanisms are problematic
Reviewed-by: darcy
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Tue Jan 27 17:50:53 2009 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Tue Jan 27 18:38:39 2009 -0800
@@ -83,7 +83,7 @@
cpString = appendPath(docletPath, cpString);
URL[] urls = pathToURLs(cpString);
if (docletParentClassLoader == null)
- appClassLoader = new URLClassLoader(urls);
+ appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
else
appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
@@ -98,6 +98,57 @@
docletClass = dc;
}
+ /*
+ * Returns the delegation class loader to use when creating
+ * appClassLoader (used to load the doclet). The context class
+ * loader is the best choice, but legacy behavior was to use the
+ * default delegation class loader (aka system class loader).
+ *
+ * Here we favor using the context class loader. To ensure
+ * compatibility with existing apps, we revert to legacy
+ * behavior if either or both of the following conditions hold:
+ *
+ * 1) the doclet is loadable from the system class loader but not
+ * from the context class loader,
+ *
+ * 2) this.getClass() is loadable from the system class loader but not
+ * from the context class loader.
+ */
+ private ClassLoader getDelegationClassLoader(String docletClassName) {
+ ClassLoader ctxCL = Thread.currentThread().getContextClassLoader();
+ ClassLoader sysCL = ClassLoader.getSystemClassLoader();
+ if (sysCL == null)
+ return ctxCL;
+ if (ctxCL == null)
+ return sysCL;
+
+ // Condition 1.
+ try {
+ sysCL.loadClass(docletClassName);
+ try {
+ ctxCL.loadClass(docletClassName);
+ } catch (ClassNotFoundException e) {
+ return sysCL;
+ }
+ } catch (ClassNotFoundException e) {
+ }
+
+ // Condition 2.
+ try {
+ if (getClass() == sysCL.loadClass(getClass().getName())) {
+ try {
+ if (getClass() != ctxCL.loadClass(getClass().getName()))
+ return sysCL;
+ } catch (ClassNotFoundException e) {
+ return sysCL;
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ }
+
+ return ctxCL;
+ }
+
/**
* Generate documentation here. Return true on success.
*/
@@ -231,6 +282,8 @@
docletClassName, methodName);
throw new DocletInvokeException();
}
+ ClassLoader savedCCL =
+ Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(appClassLoader);
return meth.invoke(null , params);
@@ -256,6 +309,8 @@
exc.getTargetException().printStackTrace();
}
throw new DocletInvokeException();
+ } finally {
+ Thread.currentThread().setContextClassLoader(savedCCL);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/6176978/T6176978.java Tue Jan 27 18:38:39 2009 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6176978
+ * @summary current Javadoc's invocation and extension (Doclet) mechanisms are problematic
+ * @build T6176978
+ * @run main T6176978
+ */
+
+import java.io.*;
+import java.net.*;
+
+public class T6176978
+{
+ public static void main(String[] args) throws Exception {
+ // create and use a temp dir that will not be on jtreg's
+ // default class path
+ File tmpDir = new File("tmp");
+ tmpDir.mkdirs();
+
+ File testSrc = new File(System.getProperty("test.src", "."));
+ String[] javac_args = {
+ "-d",
+ "tmp",
+ new File(testSrc, "X.java").getPath()
+ };
+
+ int rc = com.sun.tools.javac.Main.compile(javac_args);
+ if (rc != 0)
+ throw new Error("javac exit code: " + rc);
+
+ String[] jdoc_args = {
+ "-doclet",
+ "X",
+ new File(testSrc, "T6176978.java").getPath()
+ };
+
+ rc = com.sun.tools.javadoc.Main.execute(jdoc_args);
+ if (rc == 0)
+ throw new Error("javadoc unexpectedly succeeded");
+
+
+
+ Thread currThread = Thread.currentThread();
+ ClassLoader saveClassLoader = currThread.getContextClassLoader();
+ URLClassLoader urlCL = new URLClassLoader(new URL[] { tmpDir.toURL() });
+ currThread.setContextClassLoader(urlCL);
+
+ try {
+ rc = com.sun.tools.javadoc.Main.execute(jdoc_args);
+ if (rc != 0)
+ throw new Error("javadoc exit: " + rc);
+ }
+ finally {
+ currThread.setContextClassLoader(saveClassLoader);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/6176978/X.java Tue Jan 27 18:38:39 2009 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import com.sun.javadoc.*;
+
+public class X {
+ public static boolean start(RootDoc root) {
+ System.out.println("X.start");
+ return true;
+ }
+}