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