R
Romain
Hi everybody,
I'm trying to write a plugin-like system for Tomcat. The plugin is a
class with some default method. All plugins must extend this base
class.
Here is my architecure :
/WEB-INF/classes/GenericRule.class
....
/somewhere-not-related-to-tomcat/classes/MyRule.class
I don't want to put the MyRule.class inside the WEB-INF repository
because MyRule doesn't belong to me. It's written by somebody else.
WEB-INF should contain only my proper code and all specific code should
go elsewhere.
Problem womes with the Tomcat ClassLoader. Everything works correctly
in a standalone application but not inside Tomcat because Tomcat
ClassLoader is not really a standard one.
Here is a snippet of my code (factory of rule) :
String myRuleClassname;
Object obj = null;
URL[] urls = new URL[1];
urls[0] = (new
String("/somewhere-not-related-to-tomcat/classes")).toURL();
ClassLoader cl = GenericRule.class.getClass().getClassLoader();
if (cl != null) {
System.out.println("Default ClassLoader : " + cl);
URLClassLoader urlc = new URLClassLoader(urls, cl);
obj = urlc.loadClass(myRuleClassname);
} else {
ClassLoader cl2 = ClassLoader.getSystemClassLoader();
if (cl2 != null) {
System.out.println("System ClassLoader : " + cl2);
URLClassLoader urlc = new URLClassLoader(urls, cl2);
obj = urlc.loadClass(myRuleClassname);
} else {
System.out.println("No ClassLoader found !");
URLClassLoader urlc = new URLClassLoader(urls);
obj = urlc.loadClass(myRuleClassname);
}
}
if( obj instanceof GenericRule ){
// Good
} else {
// Bad : I didn't instanciate correctly my Object.
}
Result of this is : default classLoader is void. System class loader is
"sun.misc.Launcher$AppClassLoader@1813fac".
If I try to load myRule with the SystemClassLoader, there is an
exception because GenericRule cannot be found. Which mean that System
class loader is not the one with the webapp specific classpath.
If I try to load myRule without any parent ClassLoader, the same
exception occurs which is normal.
If I modify the array of URL in the URlClassLoader to add the
WEB-INF/lib and WEB-INF/classes path, the instanciation goes correctly,
but myRule extends the GenericRule from the URLClassLoader, not the one
from Tomcat (in this cas, there is 2 types GenericRule, one for each
classloader). So, obj is not of type GenericRule. If I cast to
genericRule, I have a ClassCastException.
The last two behaviors are normal. The only way to load properly the
plugin is to be sure that the taken GenericRule is the one defined in
the first ClassLoader. My problem is that I can't find a way to get the
Tomcat ClassLoader with the GenericRule class defined.
I hope I've been clear enough...
If anyone has any idea, let me know, you will save my week
I'm trying to write a plugin-like system for Tomcat. The plugin is a
class with some default method. All plugins must extend this base
class.
Here is my architecure :
/WEB-INF/classes/GenericRule.class
....
/somewhere-not-related-to-tomcat/classes/MyRule.class
I don't want to put the MyRule.class inside the WEB-INF repository
because MyRule doesn't belong to me. It's written by somebody else.
WEB-INF should contain only my proper code and all specific code should
go elsewhere.
Problem womes with the Tomcat ClassLoader. Everything works correctly
in a standalone application but not inside Tomcat because Tomcat
ClassLoader is not really a standard one.
Here is a snippet of my code (factory of rule) :
String myRuleClassname;
Object obj = null;
URL[] urls = new URL[1];
urls[0] = (new
String("/somewhere-not-related-to-tomcat/classes")).toURL();
ClassLoader cl = GenericRule.class.getClass().getClassLoader();
if (cl != null) {
System.out.println("Default ClassLoader : " + cl);
URLClassLoader urlc = new URLClassLoader(urls, cl);
obj = urlc.loadClass(myRuleClassname);
} else {
ClassLoader cl2 = ClassLoader.getSystemClassLoader();
if (cl2 != null) {
System.out.println("System ClassLoader : " + cl2);
URLClassLoader urlc = new URLClassLoader(urls, cl2);
obj = urlc.loadClass(myRuleClassname);
} else {
System.out.println("No ClassLoader found !");
URLClassLoader urlc = new URLClassLoader(urls);
obj = urlc.loadClass(myRuleClassname);
}
}
if( obj instanceof GenericRule ){
// Good
} else {
// Bad : I didn't instanciate correctly my Object.
}
Result of this is : default classLoader is void. System class loader is
"sun.misc.Launcher$AppClassLoader@1813fac".
If I try to load myRule with the SystemClassLoader, there is an
exception because GenericRule cannot be found. Which mean that System
class loader is not the one with the webapp specific classpath.
If I try to load myRule without any parent ClassLoader, the same
exception occurs which is normal.
If I modify the array of URL in the URlClassLoader to add the
WEB-INF/lib and WEB-INF/classes path, the instanciation goes correctly,
but myRule extends the GenericRule from the URLClassLoader, not the one
from Tomcat (in this cas, there is 2 types GenericRule, one for each
classloader). So, obj is not of type GenericRule. If I cast to
genericRule, I have a ClassCastException.
The last two behaviors are normal. The only way to load properly the
plugin is to be sure that the taken GenericRule is the one defined in
the first ClassLoader. My problem is that I can't find a way to get the
Tomcat ClassLoader with the GenericRule class defined.
I hope I've been clear enough...
If anyone has any idea, let me know, you will save my week