6176978: current Javadoc's invocation and extension (Doclet) mechanisms are problematic

Reviewed-by: darcy
This commit is contained in:
Jonathan Gibbons 2009-01-27 18:38:39 -08:00
parent f82d6e454b
commit 4aefa80bf1
3 changed files with 167 additions and 1 deletions

View file

@ -83,7 +83,7 @@ public class DocletInvoker {
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 @@ public class DocletInvoker {
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 @@ public class DocletInvoker {
docletClassName, methodName);
throw new DocletInvokeException();
}
ClassLoader savedCCL =
Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(appClassLoader);
return meth.invoke(null , params);
@ -256,6 +309,8 @@ public class DocletInvoker {
exc.getTargetException().printStackTrace();
}
throw new DocletInvokeException();
} finally {
Thread.currentThread().setContextClassLoader(savedCCL);
}
}