Tue, 27 Jan 2009 18:38:39 -0800
6176978: current Javadoc's invocation and extension (Doclet) mechanisms are problematic
Reviewed-by: darcy
1.1 --- a/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Tue Jan 27 17:50:53 2009 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Tue Jan 27 18:38:39 2009 -0800 1.3 @@ -83,7 +83,7 @@ 1.4 cpString = appendPath(docletPath, cpString); 1.5 URL[] urls = pathToURLs(cpString); 1.6 if (docletParentClassLoader == null) 1.7 - appClassLoader = new URLClassLoader(urls); 1.8 + appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName)); 1.9 else 1.10 appClassLoader = new URLClassLoader(urls, docletParentClassLoader); 1.11 1.12 @@ -98,6 +98,57 @@ 1.13 docletClass = dc; 1.14 } 1.15 1.16 + /* 1.17 + * Returns the delegation class loader to use when creating 1.18 + * appClassLoader (used to load the doclet). The context class 1.19 + * loader is the best choice, but legacy behavior was to use the 1.20 + * default delegation class loader (aka system class loader). 1.21 + * 1.22 + * Here we favor using the context class loader. To ensure 1.23 + * compatibility with existing apps, we revert to legacy 1.24 + * behavior if either or both of the following conditions hold: 1.25 + * 1.26 + * 1) the doclet is loadable from the system class loader but not 1.27 + * from the context class loader, 1.28 + * 1.29 + * 2) this.getClass() is loadable from the system class loader but not 1.30 + * from the context class loader. 1.31 + */ 1.32 + private ClassLoader getDelegationClassLoader(String docletClassName) { 1.33 + ClassLoader ctxCL = Thread.currentThread().getContextClassLoader(); 1.34 + ClassLoader sysCL = ClassLoader.getSystemClassLoader(); 1.35 + if (sysCL == null) 1.36 + return ctxCL; 1.37 + if (ctxCL == null) 1.38 + return sysCL; 1.39 + 1.40 + // Condition 1. 1.41 + try { 1.42 + sysCL.loadClass(docletClassName); 1.43 + try { 1.44 + ctxCL.loadClass(docletClassName); 1.45 + } catch (ClassNotFoundException e) { 1.46 + return sysCL; 1.47 + } 1.48 + } catch (ClassNotFoundException e) { 1.49 + } 1.50 + 1.51 + // Condition 2. 1.52 + try { 1.53 + if (getClass() == sysCL.loadClass(getClass().getName())) { 1.54 + try { 1.55 + if (getClass() != ctxCL.loadClass(getClass().getName())) 1.56 + return sysCL; 1.57 + } catch (ClassNotFoundException e) { 1.58 + return sysCL; 1.59 + } 1.60 + } 1.61 + } catch (ClassNotFoundException e) { 1.62 + } 1.63 + 1.64 + return ctxCL; 1.65 + } 1.66 + 1.67 /** 1.68 * Generate documentation here. Return true on success. 1.69 */ 1.70 @@ -231,6 +282,8 @@ 1.71 docletClassName, methodName); 1.72 throw new DocletInvokeException(); 1.73 } 1.74 + ClassLoader savedCCL = 1.75 + Thread.currentThread().getContextClassLoader(); 1.76 try { 1.77 Thread.currentThread().setContextClassLoader(appClassLoader); 1.78 return meth.invoke(null , params); 1.79 @@ -256,6 +309,8 @@ 1.80 exc.getTargetException().printStackTrace(); 1.81 } 1.82 throw new DocletInvokeException(); 1.83 + } finally { 1.84 + Thread.currentThread().setContextClassLoader(savedCCL); 1.85 } 1.86 } 1.87
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javadoc/6176978/T6176978.java Tue Jan 27 18:38:39 2009 -0800 2.3 @@ -0,0 +1,80 @@ 2.4 +/* 2.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 2.24 + * have any questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 6176978 2.30 + * @summary current Javadoc's invocation and extension (Doclet) mechanisms are problematic 2.31 + * @build T6176978 2.32 + * @run main T6176978 2.33 + */ 2.34 + 2.35 +import java.io.*; 2.36 +import java.net.*; 2.37 + 2.38 +public class T6176978 2.39 +{ 2.40 + public static void main(String[] args) throws Exception { 2.41 + // create and use a temp dir that will not be on jtreg's 2.42 + // default class path 2.43 + File tmpDir = new File("tmp"); 2.44 + tmpDir.mkdirs(); 2.45 + 2.46 + File testSrc = new File(System.getProperty("test.src", ".")); 2.47 + String[] javac_args = { 2.48 + "-d", 2.49 + "tmp", 2.50 + new File(testSrc, "X.java").getPath() 2.51 + }; 2.52 + 2.53 + int rc = com.sun.tools.javac.Main.compile(javac_args); 2.54 + if (rc != 0) 2.55 + throw new Error("javac exit code: " + rc); 2.56 + 2.57 + String[] jdoc_args = { 2.58 + "-doclet", 2.59 + "X", 2.60 + new File(testSrc, "T6176978.java").getPath() 2.61 + }; 2.62 + 2.63 + rc = com.sun.tools.javadoc.Main.execute(jdoc_args); 2.64 + if (rc == 0) 2.65 + throw new Error("javadoc unexpectedly succeeded"); 2.66 + 2.67 + 2.68 + 2.69 + Thread currThread = Thread.currentThread(); 2.70 + ClassLoader saveClassLoader = currThread.getContextClassLoader(); 2.71 + URLClassLoader urlCL = new URLClassLoader(new URL[] { tmpDir.toURL() }); 2.72 + currThread.setContextClassLoader(urlCL); 2.73 + 2.74 + try { 2.75 + rc = com.sun.tools.javadoc.Main.execute(jdoc_args); 2.76 + if (rc != 0) 2.77 + throw new Error("javadoc exit: " + rc); 2.78 + } 2.79 + finally { 2.80 + currThread.setContextClassLoader(saveClassLoader); 2.81 + } 2.82 + } 2.83 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javadoc/6176978/X.java Tue Jan 27 18:38:39 2009 -0800 3.3 @@ -0,0 +1,31 @@ 3.4 +/* 3.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 3.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 3.24 + * have any questions. 3.25 + */ 3.26 + 3.27 +import com.sun.javadoc.*; 3.28 + 3.29 +public class X { 3.30 + public static boolean start(RootDoc root) { 3.31 + System.out.println("X.start"); 3.32 + return true; 3.33 + } 3.34 +}