Glen, I also didn't think that AxisClassLodaer was doing what it should, but rather, I was thinking to extend it a bit. I don't care about the class cache, but I have my own classloader that does what I need. Currently I had to go crazy with Axis and do things like this: ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(myApp.getSharedClassLoader()); try { // rely request to Axis or call its functions } finally { Thread.currentThread().setContextClassLoader(oldLoader); } I also had to derive a Servlet from AxisServlet to be able to substitute necessary classloader. In my code I can simply go myApp.getSharedClassLoader().loadClass(...) for basic class lookup.
The thing is that there is no other way of letting Axis run with another classloader, so it always resolves to either a classloader of the thread calling things like deploy/undeploy or a servlet that invokes the pipeline or creates the engine. Now, the biggest problem is that all three contexts are different and basically unrelated (unless, of course, you do some real work about it). Would it not make sense to extend AxisClassLoader with a registry of application classloaders that have to be called in an orderly manner? Then Axis would always do something like save thread context classloader for each cl thread context <- cl Class.forName if found, break etc. thread context <- saved classloader -- Igor Sedukhin .. ([EMAIL PROTECTED]) -- (631) 342-4325 .. 1 CA Plaza, Islandia, NY 11788 -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] Sent: Thursday, February 07, 2002 10:09 PM To: [EMAIL PROTECTED] Subject: cvs commit: xml-axis/java/src/org/apache/axis/utils/compiler Javac.java gdaniels 02/02/07 19:09:26 Modified: java/src/org/apache/axis AxisEngine.java MessageContext.java java/src/org/apache/axis/handlers JWSProcessor.java java/src/org/apache/axis/message RPCHandler.java java/src/org/apache/axis/providers/java JavaProvider.java java/src/org/apache/axis/server AxisServer.java java/src/org/apache/axis/utils Admin.java java/src/org/apache/axis/utils/compiler Javac.java Added: java/src/org/apache/axis/utils JWSClassLoader.java java/src/org/apache/axis/utils/cache ClassCache.java Log: Get rid of AxisClassLoader, which was trying to wear too many hats. Split the code functionality into JWSClassLoader, a simple ClassLoader extension which allows us to reload JWS classes easily, and ClassCache, a repository for JavaClass objects. MessageContext.getClassLoader() now always returns the thread's contextClassLoader EXCEPT when that has been replaced by the JWSProcessor with a JWSClassLoader. So... 1) our code is simpler, and 2) changing a JWS file now actually causes the class to reload on the next hit (this hadn't been working for some time now). NOTES: I've left the AxisClassLoader class for now, although the only thing that references it is the JUnit test which tests that class. I plan to delete it entirely if people are happy with these changes. I'm a little dubious about the lookups in JavaMethod, which seem to be the only real reason for having the ClassCache around in the first place. Do these really improve performance that much? Revision Changes Path 1.67 +7 -1 xml-axis/java/src/org/apache/axis/AxisEngine.java Index: AxisEngine.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/AxisEngine.java,v retrieving revision 1.66 retrieving revision 1.67 diff -u -r1.66 -r1.67 --- AxisEngine.java 4 Feb 2002 20:19:05 -0000 1.66 +++ AxisEngine.java 8 Feb 2002 03:09:25 -0000 1.67 @@ -67,6 +67,7 @@ import org.apache.axis.session.Session; import org.apache.axis.session.SimpleSession; import org.apache.axis.utils.JavaUtils; +import org.apache.axis.utils.cache.ClassCache; import org.apache.axis.providers.java.RPCProvider; import org.apache.axis.providers.java.MsgProvider; import org.apache.log4j.Category; @@ -112,7 +113,8 @@ /** Should we save the engine config each time we modify it? */ protected boolean shouldSaveConfig = false; - //protected SupplierRegistry listenerRegistry = new SupplierRegistry(); + /** Java class cache */ + protected ClassCache classCache = new ClassCache(); /** * This engine's Session. This Session supports "application scope" @@ -374,5 +376,9 @@ */ public Session getApplicationSession () { return session; + } + + public ClassCache getClassCache() { + return classCache; } }; 1.71 +4 -5 xml-axis/java/src/org/apache/axis/MessageContext.java Index: MessageContext.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/MessageContext.java,v retrieving revision 1.70 retrieving revision 1.71 diff -u -r1.70 -r1.71 --- MessageContext.java 4 Feb 2002 20:19:06 -0000 1.70 +++ MessageContext.java 8 Feb 2002 03:09:25 -0000 1.71 @@ -59,7 +59,6 @@ import org.apache.axis.encoding.TypeMappingRegistry; import org.apache.axis.handlers.soap.SOAPService; import org.apache.axis.session.Session; -import org.apache.axis.utils.AxisClassLoader; import org.apache.log4j.Category; import java.util.Hashtable; @@ -121,7 +120,7 @@ /** * The default classloader that this service should use */ - private AxisClassLoader classLoader ; + private ClassLoader classLoader ; /** * The AxisEngine which this context is involved with @@ -375,13 +374,13 @@ return timeout; } - public AxisClassLoader getClassLoader() { + public ClassLoader getClassLoader() { if ( classLoader == null ) - classLoader = AxisClassLoader.getClassLoader(); + classLoader = Thread.currentThread().getContextClassLoader(); return( classLoader ); } - public void setClassLoader(AxisClassLoader cl ) { + public void setClassLoader(ClassLoader cl ) { classLoader = cl ; } 1.36 +12 -12 xml-axis/java/src/org/apache/axis/handlers/JWSProcessor.java Index: JWSProcessor.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/handlers/JWSProcessor.java,v retrieving revision 1.35 retrieving revision 1.36 diff -u -r1.35 -r1.36 --- JWSProcessor.java 4 Feb 2002 23:34:09 -0000 1.35 +++ JWSProcessor.java 8 Feb 2002 03:09:25 -0000 1.36 @@ -60,7 +60,7 @@ import org.apache.axis.MessageContext; import org.apache.axis.providers.java.RPCProvider; import org.apache.axis.transport.http.HTTPConstants; -import org.apache.axis.utils.AxisClassLoader; +import org.apache.axis.utils.JWSClassLoader; import org.apache.axis.utils.JavaUtils; import org.apache.axis.utils.XMLUtils; import org.apache.axis.utils.compiler.Compiler; @@ -70,12 +70,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -250,12 +245,17 @@ JavaUtils.getMessage("badCompile00", jFile), null, new Element[] { root } ); } - AxisClassLoader.removeClassLoader( clsName ); + JWSClassLoader.removeClassLoader( clsName ); } - AxisClassLoader cl = msgContext.getClassLoader(); - if ( !cl.isClassRegistered(clsName) ) - cl.registerClass( clsName, cFile ); - msgContext.setClassLoader( cl ); + + JWSClassLoader cl = JWSClassLoader.getClassLoader(clsName); + if (cl == null) { + cl = new JWSClassLoader(clsName, + msgContext.getClassLoader(), + cFile); + } + + msgContext.setClassLoader(cl); /* Create a new RPCProvider - this will be the "service" */ /* that we invoke. */ 1.24 +5 -4 xml-axis/java/src/org/apache/axis/message/RPCHandler.java Index: RPCHandler.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/RPCHandler.java,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- RPCHandler.java 26 Jan 2002 02:47:22 -0000 1.23 +++ RPCHandler.java 8 Feb 2002 03:09:25 -0000 1.24 @@ -70,9 +70,9 @@ import org.apache.axis.encoding.DeserializerImpl; import org.apache.axis.encoding.TypeMapping; import org.apache.axis.encoding.FieldTarget; -import org.apache.axis.utils.AxisClassLoader; import org.apache.axis.utils.JavaUtils; import org.apache.axis.utils.cache.JavaClass; +import org.apache.axis.utils.cache.ClassCache; import org.apache.log4j.Category; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -106,9 +106,10 @@ String clsName = (String) service.getOption( "className" ); try { - AxisClassLoader cl = msgContext.getClassLoader(); - JavaClass jc = cl.lookup(clsName); - Class cls = jc.getJavaClass(); + ClassLoader cl = msgContext.getClassLoader(); + ClassCache cache = msgContext.getAxisEngine().getClassCache(); + JavaClass jc = cache.lookup(clsName, cl); + Class cls = jc.getJavaClass(); if (category.isDebugEnabled()) { category.debug(JavaUtils.getMessage( 1.34 +5 -4 xml-axis/java/src/org/apache/axis/providers/java/JavaProvider.java Index: JavaProvider.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/providers/java/JavaProvider.java,v retrieving revision 1.33 retrieving revision 1.34 diff -u -r1.33 -r1.34 --- JavaProvider.java 1 Feb 2002 22:08:26 -0000 1.33 +++ JavaProvider.java 8 Feb 2002 03:09:25 -0000 1.34 @@ -63,9 +63,9 @@ import org.apache.axis.MessageContext; import org.apache.axis.message.SOAPEnvelope; import org.apache.axis.providers.BasicProvider; -import org.apache.axis.utils.AxisClassLoader; import org.apache.axis.utils.JavaUtils; import org.apache.axis.utils.cache.JavaClass; +import org.apache.axis.utils.cache.ClassCache; import org.apache.axis.wsdl.fromJava.Emitter; import org.apache.axis.encoding.TypeMapping; import org.apache.axis.Constants; @@ -300,7 +300,7 @@ } try { - AxisClassLoader cl = msgContext.getClassLoader(); + ClassLoader cl = msgContext.getClassLoader(); Class cls = jc.getJavaClass(); String url = msgContext.getStrProp(MessageContext.TRANS_URL); String urn = (String)msgContext.getTargetService(); @@ -350,8 +350,9 @@ String clsName) throws Exception { - AxisClassLoader cl = msgContext.getClassLoader(); - JavaClass jc = cl.lookup(clsName); + ClassLoader cl = msgContext.getClassLoader(); + ClassCache cache = msgContext.getAxisEngine().getClassCache(); + JavaClass jc = cache.lookup(clsName, cl); return jc.getJavaClass().newInstance(); } 1.57 +2 -3 xml-axis/java/src/org/apache/axis/server/AxisServer.java Index: AxisServer.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/server/AxisServer.java,v retrieving revision 1.56 retrieving revision 1.57 diff -u -r1.56 -r1.57 --- AxisServer.java 5 Feb 2002 16:25:38 -0000 1.56 +++ AxisServer.java 8 Feb 2002 03:09:25 -0000 1.57 @@ -64,7 +64,6 @@ import org.apache.axis.SimpleTargetedChain; import org.apache.axis.client.AxisClient; import org.apache.axis.configuration.DefaultEngineConfigurationFactory; -import org.apache.axis.utils.AxisClassLoader; import org.apache.axis.utils.JavaUtils; import org.apache.log4j.Category; @@ -186,7 +185,7 @@ hName = msgContext.getStrProp( MessageContext.ENGINE_HANDLER ); if ( hName != null ) { if ( (h = getHandler(hName)) == null ) { - AxisClassLoader cl = msgContext.getClassLoader(); + ClassLoader cl = msgContext.getClassLoader(); try { category.debug( JavaUtils.getMessage("tryingLoad00", hName) ); Class cls = cl.loadClass( hName ); @@ -339,7 +338,7 @@ hName = msgContext.getStrProp( MessageContext.ENGINE_HANDLER ); if ( hName != null ) { if ( (h = getHandler(hName)) == null ) { - AxisClassLoader cl = msgContext.getClassLoader(); + ClassLoader cl = msgContext.getClassLoader(); try { category.debug( JavaUtils.getMessage("tryingLoad00", hName) ); Class cls = cl.loadClass( hName ); 1.96 +2 -2 xml-axis/java/src/org/apache/axis/utils/Admin.java Index: Admin.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/Admin.java,v retrieving revision 1.95 retrieving revision 1.96 diff -u -r1.95 -r1.96 --- Admin.java 5 Feb 2002 16:25:39 -0000 1.95 +++ Admin.java 8 Feb 2002 03:09:25 -0000 1.96 @@ -271,7 +271,7 @@ try { String action = rootName; - AxisClassLoader cl = AxisClassLoader.getClassLoader(); + ClassLoader cl = msgContext.getClassLoader(); if ( !action.equals("clientdeploy") && !action.equals("deploy") && !action.equals("undeploy") && @@ -570,7 +570,7 @@ WSDDDeployment deployment) throws Exception { - AxisClassLoader cl = AxisClassLoader.getClassLoader(); + ClassLoader cl = AxisClassLoader.getClassLoader(); String name = elem.getAttribute( "name" ); WSDDHandler handler; 1.1 xml-axis/java/src/org/apache/axis/utils/JWSClassLoader.java Index: JWSClassLoader.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Axis" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.axis.utils; import java.util.Hashtable; import java.io.FileInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * Class loader for JWS files. There is one of these per JWS class, and * we keep a static Hashtable of them, indexed by class name. When we want * to reload a JWS, we replace the ClassLoader for that class and let the * old one get GC'ed. * * This is a simplified version of the former AxisClassLoader. * * @author Glen Daniels ([EMAIL PROTECTED]) * @author Doug Davis ([EMAIL PROTECTED]) */ public class JWSClassLoader extends ClassLoader { private static Hashtable classloaders = new Hashtable(); /** * Construct a JWSClassLoader with a class name, a parent ClassLoader, * and a filename of a .class file containing the bytecode for the class. * The constructor will load the bytecode, define the class, and register * this JWSClassLoader in the static registry. * * @param name the name of the class which will be created/loaded * @param cl the parent ClassLoader * @param classFile filename of the .class file * @exception FileNotFoundException * @exception IOException */ public JWSClassLoader(String name, ClassLoader cl, String classFile) throws FileNotFoundException, IOException { super(cl); FileInputStream fis = new FileInputStream( classFile ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte buf[] = new byte[1024]; for(int i = 0; (i = fis.read(buf)) != -1; ) baos.write(buf, 0, i); fis.close(); baos.close(); /* Create a new Class object from it */ /*************************************/ byte[] data = baos.toByteArray(); Class cls = defineClass( name, data, 0, data.length ); classloaders.put(name, this); } /** * Obtain the JWSClassLoader (if any) associated with the given * className. * * @param className the name of a class */ public static JWSClassLoader getClassLoader(String className) { if (className == null) return null; return (JWSClassLoader)classloaders.get(className); } /** * Deregister the JWSClassLoader for a given className. * * @param className the name of a class */ public static void removeClassLoader(String className) { classloaders.remove(className); } } 1.1 xml-axis/java/src/org/apache/axis/utils/cache/ClassCache.java Index: ClassCache.java =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Axis" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.axis.utils.cache; import java.util.Hashtable; /** * A cache class for JavaClass objects, which enables us to quickly reference * methods. * * @author Doug Davis ([EMAIL PROTECTED]) * @author Glen Daniels ([EMAIL PROTECTED]) */ public class ClassCache { Hashtable classCache = new Hashtable(); public ClassCache() { } /** * Register a class in the cache. Creates a new JavaClass object * around the given class, and inserts it into the Hashtable, replacing * any previous entry. * * @param name the name of the class. * @param cls a Java Class. */ public synchronized void registerClass(String name, Class cls) { if (name == null) return; // ??? Should we let this NPE? JavaClass oldClass = (JavaClass) classCache.get(name); if (oldClass != null && oldClass.getJavaClass() == cls) return; classCache.put(name, new JavaClass(cls)); } /** * Remove an entry from the cache. * * @param name the name of the class to remove. */ public synchronized void deregisterClass(String name) { classCache.remove(name); } /** * Query a given class' cache status. * * @param name a class name * @return true if the class is in the cache, false otherwise */ public boolean isClassRegistered(String name) { return (classCache != null && classCache.get(name) != null); } /** * Find the cached JavaClass entry for this class, creating one * if necessary. * @param className name of the class desired * @param cl ClassLoader to use if we need to load the class * @return JavaClass entry */ public JavaClass lookup(String className, ClassLoader cl) throws ClassNotFoundException { JavaClass jc = (JavaClass) classCache.get(className); if ((jc == null) && (cl != null)) { // Try to load the class with the specified classloader Class cls = cl.loadClass(className); jc = new JavaClass(cls); } return jc; } } ; 1.3 +2 -3 xml-axis/java/src/org/apache/axis/utils/compiler/Javac.java Index: Javac.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/compiler/Javac.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Javac.java 11 Dec 2001 13:16:38 -0000 1.2 +++ Javac.java 8 Feb 2002 03:09:26 -0000 1.3 @@ -55,7 +55,6 @@ package org.apache.axis.utils.compiler; -import org.apache.axis.utils.AxisClassLoader; import org.apache.log4j.Category; import java.io.BufferedReader; @@ -73,7 +72,7 @@ * * @author <a href="mailto:[EMAIL PROTECTED]">Davanum Srinivas</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a> - * @version $Revision: 1.2 $ $Date: 2001/12/11 13:16:38 $ + * @version $Revision: 1.3 $ $Date: 2002/02/08 03:09:26 $ * @since 2.0 */ @@ -90,7 +89,7 @@ public Javac() { // Use reflection to be able to build on all JDKs - AxisClassLoader cl = AxisClassLoader.getClassLoader(); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); try { cl.loadClass(MODERN_CLASS); modern = true;