Hello Kurt,

I can see why you might want to do this to create your own sort of
mini-container running outside another running Tomcat's JVM, but It
appears that you are running this within a currently running Tomcat
container.  Why do you need to do this?  To be honest, I know how to
deal with some common classloading issues, but I don't know so much
about using a custom classloader.  This might be a Tomcat-Dev list
question.

Jake

Monday, December 16, 2002, 9:35:07 AM, you wrote:

KH> Have a look.  Let me know what you think.
KH> ---------------------------------------------------

KH> import java.io.*;
KH> import java.lang.reflect.Method;
KH> import java.net.*;
KH> import java.util.*;

KH> import javax.servlet.http.*;
KH> import javax.servlet.*;

KH> public class ServletCaller
KH> {
KH>         public static void callServlet(
KH>                 String servletName,
KH>                 ServletConfig config,
KH>                 HttpServletRequest req,
KH>                 HttpServletResponse resp)
KH>                 throws Exception
KH>         {
KH>                 Class[] doGetArgTypes =
KH>                         { HttpServletRequest.class, HttpServletResponse.class };
KH>                 Class[] initArgType = { ServletConfig.class };
KH>                 Object[] doGetArgs = { req, resp };
KH>                 Object[] initArg = { config };

KH>                 ServletClassLoader ldr = new ServletClassLoader(getParentLoader());
KH>                 Class clz = ldr.loadClass(servletName, true);
KH>                 Object servlet = clz.newInstance();  // Blows up here

KH>                 Method initMethod = clz.getMethod("init",initArgType);
KH>                 Method doGetMethod = clz.getMethod("doGet",doGetArgTypes);
KH>                 initMethod.invoke(servlet, initArg);
KH>                 doGetMethod.invoke(servlet, doGetArgs);
KH>                 // RequestDispatcher won't work!!!
KH>                 // Using a custom HttpResponse object to read servlet output
KH>         }

KH>         public static Class getServletClass(String servletName) throws Exception
KH>         {
KH>                 ServletClassLoader ldr = new ServletClassLoader();
KH>                 Class clz = ldr.loadClass(servletName);

KH>                 return clz;
KH>         }

KH>         private static class ServletClassLoader extends ClassLoader
KH>         {

KH>                 private Hashtable classes = new Hashtable();
KH>                 private String root;

KH>                 public ServletClassLoader(ClassLoader parent)
KH>                 {
KH>                         super(parent);
KH>                         String rootDir = System.getProperty("SERVLETDIR");
KH>                         if (rootDir == null)
KH>                                 throw new IllegalArgumentException("Null root 
directory");
KH>                         root = rootDir;
KH>                 }

KH>                 public ServletClassLoader()
KH>                 {
KH>                         super(ClassLoader.getSystemClassLoader());
KH>                         String rootDir = System.getProperty("SERVLETDIR");
KH>                         if (rootDir == null)
KH>                                 throw new IllegalArgumentException("Null root 
directory");
KH>                         root = rootDir;
KH>                 }

KH>                 protected Class loadClass(String name, boolean resolve)
KH>                         throws ClassNotFoundException
KH>                 {
KH>                         Class clas = null;
KH>                         System.out.println("\nAttempting to load class: " + name);

KH>                         clas = findClass(name);
KH>                         if (clas != null) {
KH>                                 if (resolve)
KH>                                         resolveClass(clas);
KH>                                 return clas;
KH>                         }

KH>                         if (clas == null)
KH>                         {
KH>                                 try {
KH>                                         byte[] buff = loadClassData(name);
KH>                                         clas = defineClass(name, buff, 0, 
buff.length);
KH>                                         if (resolve)
KH>                                                 resolveClass(clas);

KH>                                 }
KH>                                 catch (IOException e)
KH>                                 {
KH>                                         throw new ClassNotFoundException(
KH>                                                 "Error reading file: " + name);
KH>                                 }
KH>                         }
KH>                         classes.put(name, clas);
KH>                         return clas;
KH>                 }

KH>                 private byte[] loadClassData(String filename) throws IOException
KH>                 {
KH>                         File f = new File(root, filename + ".class");
KH>                         int size = (int) f.length();
KH>                         byte buff[] = new byte[size];
KH>                         FileInputStream fis = new FileInputStream(f);
KH>                         DataInputStream dis = new DataInputStream(fis);
KH>                         dis.readFully(buff);
KH>                         dis.close();

KH>                         return buff;
KH>                 }

KH>                 protected Class findClass(String name) throws 
ClassNotFoundException
KH>                 {
KH>                         Class clas = (Class) classes.get(name);

KH>                         System.out.println("\nClass name: " + name);

KH>                         try
KH>                         {
KH>                                 if (clas == null)
KH>                                         clas = super.findLoadedClass(name);
KH>                                 if (clas == null)
KH>                                 {
KH>                                         ClassLoader parent = getParent();
KH>                                         clas = parent.loadClass(name);
KH>                                 }
KH>                                 if (clas == null)
KH>                                         clas = super.findSystemClass(name);
KH>                         }
KH>                         catch (ClassNotFoundException e)
KH>                         {}
KH>                         if (clas != null)
KH>                         {
KH>                                 if (clas.getClassLoader() != null)
KH>                                         System.out.println(
KH>                                                 "\tClassloader: " + 
clas.getClassLoader().toString());

KH>                                 // Store for future use
KH>                                 if (classes.get(name) == null)
KH>                                         classes.put(name, clas);
KH>                         }

KH>                         return clas;
KH>                 }

KH>                 public InputStream getResourceAsStream(String name)
KH>                 {
KH>                         return getParent().getResourceAsStream(name);
KH>                 }

KH>                 public URL getResource(String name)
KH>                 {
KH>                         return getParent().getResource(name);
KH>                 }

KH>                 public Class loadClass(String name) throws ClassNotFoundException
KH>                 {
KH>                         return loadClass(name, false);
KH>                 }

KH>                 public URL findResource(String name)
KH>                 {
KH>                         return super.findResource(name);
KH>                 }

KH>                 protected Enumeration findResources(String name) throws IOException
KH>                 {
KH>                         return super.findResources(name);
KH>                 }

KH>         }

KH>         private static ClassLoader getParentLoader() throws Exception
KH>         {
KH>                 //              Vector classUrls = new Vector();
KH>                 //              String tcPath = 
""+System.getProperty("tc_path_add");
KH>                 //
KH>                 //              // Get tomcat classpath for 3.3 and later
KH>                 //              StringTokenizer tknzr = new StringTokenizer(
KH>                 //                      tcPath,File.pathSeparator);
KH>                 //              while( tknzr.hasMoreTokens() ) {
KH>                 //                      String tkn = tknzr.nextToken();
KH>                 //                      System.out.println(tkn);
KH>                 //                      classUrls.add( new URL("file:"+tkn) );
KH>                 //              }
KH>                 //
KH>                 //              tknzr = new StringTokenizer(
KH>                 //                      
System.getProperty("java.class.path"),File.pathSeparator);
KH>                 //              while( tknzr.hasMoreTokens() )
KH>                 //                      classUrls.add( new 
URL("file:"+tknzr.nextToken()) );
KH>                 //
KH>                 //              URL [] classPathArray = new URL[classUrls.size()];
KH>                 //              classUrls.copyInto( classPathArray );

KH>                 URL[] classPathArray = new URL[] {
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/common/servlet.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/common/connector_util.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/common/core_util.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/common/etomcat.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/common/jasper-runtime.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/common/tomcat_core.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/apps/xalan.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/apps/xerces.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/apps/xml4j.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/apps/xsltc.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/stop-tomcat.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/tomcat.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/container/crimson.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/container/facade22.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/container/jasper.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/container/tomcat_modules.jar"),
KH>                                 new 
URL("file://D:/apache/tomcat331/lib/container/tomcat_util.jar"),
KH>                                 };

KH>                 //              URL other_CP = new URL( 
System.getProperty("java.class.path") );
KH>                 ClassLoader loader = new URLClassLoader(classPathArray);

KH>                 //              String classPathStr = 
System.getProperty("java.class.path")
KH>                 //                      + File.pathSeparatorChar
KH>                 //                      + System.getProperty("tc_path_add");
KH>                 //              System.setProperty("java.class.path", 
classPathStr);
KH>                 //              System.out.println("\n\njava.class.path= "
KH>                 //                      +System.getProperty("java.class.path") + 
"\n\n");

KH>                 return loader;
KH>         }
KH> }

KH> ---------------------------------------------------


KH> -----Original Message-----
KH> From: Jacob Kjome [mailto:[EMAIL PROTECTED]]
KH> Sent: Monday, December 16, 2002 4:55 AM
KH> To: Tomcat Users List
KH> Subject: Re: custom ClassLoader Purgatory in Tomcat 3.3.1



KH> The classloader behavior for webapps is specified in the servlet spec to be
KH> exactly opposite that of the normal Java2 classloading behavior.  So,
KH> classes in the WebappClassLoader will *not* as the parent to load classes
KH> for it unless it can't find the class to load there first.  That's one
KH> thing to remember.  The other thing is that parent classloaders can't see
KH> their children, but children can see their parents.  If you have a class in
KH> a parent classloader which is trying to load classes or other resources in
KH> the child classloader, you will have problems....unless you use the thread
KH> context classloader.  If you use Class.forName(String) you are asking for
KH> trouble.  The other version of Class.forName() which takes 3 parameters is
KH> your ticket out of this situation since you can pass it the thread context
KH> classloader to load the resource.

KH> Anyway, I'm pretty sure you will be able to do what you are attempting to
KH> do, but without sample code, no one can help you.

KH> Jake

KH> 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
KH> 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
KH> 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
KH> 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
KH> the
>>process can check with it to see whether it's created a certain class
KH> 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
KH> 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:
KH> 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:
KH> <mailto:[EMAIL PROTECTED]>
>>For additional commands, e-mail:
KH> <mailto:[EMAIL PROTECTED]>


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



-- 
Best regards,
 Jacob                            mailto:[EMAIL PROTECTED]


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

Reply via email to