I'm still not sure what this is supposed to do, that can't be done much
easier using the standard J2EE-style ClassLoaders that Tomcat 3.3 and higher
provide.

In any case, your life will be made much easier if you use:
Thread.currentThread().getContextClassLoader()
as the parent of your CL (assuming that your code is being called from a
Servlet).  In Tomcat 3.3 and higher, this is always set to be the Web-app
ClassLoader while a Servlet is executing.  It should make a lot of the weird
errors go away, since you will be using the same ClassLoader as Tomcat to
load stuff like HttpServlet.

"Kurt Heston" <[EMAIL PROTECTED]> wrote in message
[EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
> Have a look.  Let me know what you think.
> ---------------------------------------------------
>
> import java.io.*;
> import java.lang.reflect.Method;
> import java.net.*;
> import java.util.*;
>
> import javax.servlet.http.*;
> import javax.servlet.*;
>
> public class ServletCaller
> {
> public static void callServlet(
> String servletName,
> ServletConfig config,
> HttpServletRequest req,
> HttpServletResponse resp)
> throws Exception
> {
> Class[] doGetArgTypes =
> { HttpServletRequest.class, HttpServletResponse.class };
> Class[] initArgType = { ServletConfig.class };
> Object[] doGetArgs = { req, resp };
> Object[] initArg = { config };
>
> ServletClassLoader ldr = new ServletClassLoader(getParentLoader());
> Class clz = ldr.loadClass(servletName, true);
> Object servlet = clz.newInstance();  // Blows up here
>
> Method initMethod = clz.getMethod("init",initArgType);
> Method doGetMethod = clz.getMethod("doGet",doGetArgTypes);
> initMethod.invoke(servlet, initArg);
> doGetMethod.invoke(servlet, doGetArgs);
> // RequestDispatcher won't work!!!
> // Using a custom HttpResponse object to read servlet output
> }
>
> public static Class getServletClass(String servletName) throws Exception
> {
> ServletClassLoader ldr = new ServletClassLoader();
> Class clz = ldr.loadClass(servletName);
>
> return clz;
> }
>
> private static class ServletClassLoader extends ClassLoader
> {
>
> private Hashtable classes = new Hashtable();
> private String root;
>
> public ServletClassLoader(ClassLoader parent)
> {
> super(parent);
> String rootDir = System.getProperty("SERVLETDIR");
> if (rootDir == null)
> throw new IllegalArgumentException("Null root directory");
> root = rootDir;
> }
>
> public ServletClassLoader()
> {
> super(ClassLoader.getSystemClassLoader());
> String rootDir = System.getProperty("SERVLETDIR");
> if (rootDir == null)
> throw new IllegalArgumentException("Null root directory");
> root = rootDir;
> }
>
> protected Class loadClass(String name, boolean resolve)
> throws ClassNotFoundException
> {
> Class clas = null;
> System.out.println("\nAttempting to load class: " + name);
>
> clas = findClass(name);
> if (clas != null) {
> if (resolve)
> resolveClass(clas);
> return clas;
> }
>
> if (clas == null)
> {
> try {
> byte[] buff = loadClassData(name);
> clas = defineClass(name, buff, 0, buff.length);
> if (resolve)
> resolveClass(clas);
>
> }
> catch (IOException e)
> {
> throw new ClassNotFoundException(
> "Error reading file: " + name);
> }
> }
> classes.put(name, clas);
> return clas;
> }
>
> private byte[] loadClassData(String filename) throws IOException
> {
> File f = new File(root, filename + ".class");
> int size = (int) f.length();
> byte buff[] = new byte[size];
> FileInputStream fis = new FileInputStream(f);
> DataInputStream dis = new DataInputStream(fis);
> dis.readFully(buff);
> dis.close();
>
> return buff;
> }
>
> protected Class findClass(String name) throws ClassNotFoundException
> {
> Class clas = (Class) classes.get(name);
>
> System.out.println("\nClass name: " + name);
>
> try
> {
> if (clas == null)
> clas = super.findLoadedClass(name);
> if (clas == null)
> {
> ClassLoader parent = getParent();
> clas = parent.loadClass(name);
> }
> if (clas == null)
> clas = super.findSystemClass(name);
> }
> catch (ClassNotFoundException e)
> {}
> if (clas != null)
> {
> if (clas.getClassLoader() != null)
> System.out.println(
> "\tClassloader: " + clas.getClassLoader().toString());
>
> // Store for future use
> if (classes.get(name) == null)
> classes.put(name, clas);
> }
>
> return clas;
> }
>
> public InputStream getResourceAsStream(String name)
> {
> return getParent().getResourceAsStream(name);
> }
>
> public URL getResource(String name)
> {
> return getParent().getResource(name);
> }
>
> public Class loadClass(String name) throws ClassNotFoundException
> {
> return loadClass(name, false);
> }
>
> public URL findResource(String name)
> {
> return super.findResource(name);
> }
>
> protected Enumeration findResources(String name) throws IOException
> {
> return super.findResources(name);
> }
>
> }
>
> private static ClassLoader getParentLoader() throws Exception
> {
> // Vector classUrls = new Vector();
> // String tcPath = ""+System.getProperty("tc_path_add");
> //
> // // Get tomcat classpath for 3.3 and later
> // StringTokenizer tknzr = new StringTokenizer(
> // tcPath,File.pathSeparator);
> // while( tknzr.hasMoreTokens() ) {
> // String tkn = tknzr.nextToken();
> // System.out.println(tkn);
> // classUrls.add( new URL("file:"+tkn) );
> // }
> //
> // tknzr = new StringTokenizer(
> // System.getProperty("java.class.path"),File.pathSeparator);
> // while( tknzr.hasMoreTokens() )
> // classUrls.add( new URL("file:"+tknzr.nextToken()) );
> //
> // URL [] classPathArray = new URL[classUrls.size()];
> // classUrls.copyInto( classPathArray );
>
> URL[] classPathArray = new URL[] {
> new URL("file://D:/apache/tomcat331/lib/common/servlet.jar"),
> new URL("file://D:/apache/tomcat331/lib/common/connector_util.jar"),
> new URL("file://D:/apache/tomcat331/lib/common/core_util.jar"),
> new URL("file://D:/apache/tomcat331/lib/common/etomcat.jar"),
> new URL("file://D:/apache/tomcat331/lib/common/jasper-runtime.jar"),
> new URL("file://D:/apache/tomcat331/lib/common/tomcat_core.jar"),
> new URL("file://D:/apache/tomcat331/lib/apps/xalan.jar"),
> new URL("file://D:/apache/tomcat331/lib/apps/xerces.jar"),
> new URL("file://D:/apache/tomcat331/lib/apps/xml4j.jar"),
> new URL("file://D:/apache/tomcat331/lib/apps/xsltc.jar"),
> new URL("file://D:/apache/tomcat331/lib/stop-tomcat.jar"),
> new URL("file://D:/apache/tomcat331/lib/tomcat.jar"),
> new URL("file://D:/apache/tomcat331/lib/container/crimson.jar"),
> new URL("file://D:/apache/tomcat331/lib/container/facade22.jar"),
> new URL("file://D:/apache/tomcat331/lib/container/jasper.jar"),
> new URL("file://D:/apache/tomcat331/lib/container/tomcat_modules.jar"),
> new URL("file://D:/apache/tomcat331/lib/container/tomcat_util.jar"),
> };
>
> // URL other_CP = new URL( System.getProperty("java.class.path") );
> ClassLoader loader = new URLClassLoader(classPathArray);
>
> // String classPathStr = System.getProperty("java.class.path")
> // + File.pathSeparatorChar
> // + System.getProperty("tc_path_add");
> // System.setProperty("java.class.path", classPathStr);
> // System.out.println("\n\njava.class.path= "
> // +System.getProperty("java.class.path") + "\n\n");
>
> return loader;
> }
> }
>
> ---------------------------------------------------
>
>
> -----Original Message-----
> From: Jacob Kjome [mailto:[EMAIL PROTECTED]]
> Sent: Monday, December 16, 2002 4:55 AM
> To: Tomcat Users List
> Subject: Re: custom ClassLoader Purgatory in Tomcat 3.3.1
>
>
>
> The classloader behavior for webapps is specified in the servlet spec to
be
> exactly opposite that of the normal Java2 classloading behavior.  So,
> classes in the WebappClassLoader will *not* as the parent to load classes
> for it unless it can't find the class to load there first.  That's one
> thing to remember.  The other thing is that parent classloaders can't see
> their children, but children can see their parents.  If you have a class
in
> a parent classloader which is trying to load classes or other resources in
> the child classloader, you will have problems....unless you use the thread
> context classloader.  If you use Class.forName(String) you are asking for
> trouble.  The other version of Class.forName() which takes 3 parameters is
> your ticket out of this situation since you can pass it the thread context
> classloader to load the resource.
>
> Anyway, I'm pretty sure you will be able to do what you are attempting to
> do, but without sample code, no one can help you.
>
> Jake
>
> At 12:59 AM 12/16/2002 -0800, you wrote:
> >Hello,
> >
> >I'm having issues with using a custom classloader in Tomcat 3.3.1.  I
have
> a
> >need to load servlets from a runtime-determined classpath.  The solution
> >worked fine in 3.2.x.  Here's what I think the problem is (let me know
> where
> >my understanding is flawed):
> >
> >I'm pretty confident any custom classloader that tries to load servlets
is
> >doomed on newer versions of Tomcat.  By this I mean, TC4x and TC5x won't
> >work either as they employ a similar classpath paradigm as that of
TC3.3x.
> >
> >It seems that the classloader alchemy the Jakarta people are doing to
allow
> >web application classpaths to be independent of each other and that used
by
> >the core Tomcat components is going to prevent me from instantiating a
> >servlet via a runtime-determined classpath.  A JVM process will only
allow
> a
> >single instance of any class type within its process space.  Every JVM
> >process has a SystemClassLoader that manages loading the core java stuff,
> >like the String class.  Any other classLoader in the process space that
> >tries to load a String.class object after the SystemClassLoader has done
so
> >will throw a NoClassDefFoundException or some other instantiation error.
> >
> >What's nice about the SystemClassLoader is that any other ClassLoader in
> the
> >process can check with it to see whether it's created a certain class
> before
> >trying to do so, and use the one it has.  A ClassLoader can also do this
if
> >it is chained with other class loaders.  It needs only traverse the chain
> >via the getParent() method and query each for the class in question.  The
> >problem with Tomcat creating its own class loaders is that my custom
class
> >loader has no way of knowing what classes they've loaded nor can I use
any
> >of those instances.  So, when I try to create my servlet object, its
super
> >class, HttpServlet is also instantiated and pow, the JVM dumps a stack
> trace
> >claiming it can't find resources.
> >
> >(sample Stack trace)
> >-----------------------
> >Attempting to load class: java.lang.NoClassDefFoundError
> >
> >Class name: java.lang.NoClassDefFoundError
> >2002-12-15 23:51:07 - Ctx() : Exception in R(  + /servlet/MyServlet +
> >null) - java.lang.ExceptionInInitializerError:
> >java.util.MissingResourceException: Can't find bundle for base name
> >javax.servlet.http.LocalStrings, locale en_US
> >         at
>
>java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:
> 7
> >07)
> >         at
java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:678)
> >         at java.util.ResourceBundle.getBundle(ResourceBundle.java:541)
> >         at javax.servlet.http.HttpServlet.<clinit>(HttpServlet.java)
> >-----------------------
> >
> >I'm guessing this is a nonsense error because the ResourceBundle it's
> >looking for is in the same jar that HttpServlet is in.  So, it's
definitely
> >on the classpath.
> >
> >Anyway, what else might I try to remedy this?
> >
> >Thanks.
> >
> >
> >--
> >To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> >For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>





--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to