You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@locus.apache.org on 2000/03/30 23:46:07 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/core ServletWrapper.java

costin      00/03/30 13:46:07

  Modified:    src/share/org/apache/tomcat/core ServletWrapper.java
  Log:
  Fix for #116 - JNDI ( and probably EJB and other JDK1.2 libraries ) are not
  working because the thread ClassLoader is not set.
  
  This bug affects only people using JDK1.2, but I think it's important to check
  in the fix. We're using reflection to invoke jdk1.2 methods, and it seems to
  work fine in JDK1.1.6.
  
  Thanks to  kyle.downey@ny.frb.org - it's a very tricky bug.
  ( the solution I checked in is based on his patch, but I used reflection
  instead of normal method call to keep 1.1.6 compatibility ). We just need to
  call Thread.setContextClassLoader() before executing any servlet method.
  ( we also need to revert to the previous context class loader if we are in
  include - but that happens after the request is completed so it doesn't affect
  the response time )
  
  We might need a better solution/architecture to deal with that - please -1 the
  change if you feel it's too much for Tocmat 3.1.
  
  Submitted by:	 kyle.downey@ny.frb.org
  
  Revision  Changes    Path
  1.35      +67 -3     jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java
  
  Index: ServletWrapper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- ServletWrapper.java	2000/03/29 23:31:04	1.34
  +++ ServletWrapper.java	2000/03/30 21:46:07	1.35
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java,v 1.34 2000/03/29 23:31:04 costin Exp $
  - * $Revision: 1.34 $
  - * $Date: 2000/03/29 23:31:04 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java,v 1.35 2000/03/30 21:46:07 costin Exp $
  + * $Revision: 1.35 $
  + * $Date: 2000/03/30 21:46:07 $
    *
    * ====================================================================
    *
  @@ -353,7 +353,20 @@
       
       public void handleRequest(Request req, Response res)
       {
  +	ClassLoader originalCL=null;
   	try {
  +	    // Before we do init() or service(), we need to do some tricks
  +	    // with the class loader - see bug #116.
  +	    // some JDK1.2 code will not work without this fix
  +
  +	    // we save the originalCL because we might be in include
  +	    // and we need to revert to it when we finish
  +
  +	    // that will set a new (JDK)context class loader, and return the old one
  +	    // if we are in JDK1.2
  +	    originalCL = fixJDKContextClassLoader(context.getServletLoader().getClassLoader());
  +
  +
   	    if( path != null ) {
   		// XXX call JspServlet directly, did anyone tested it ??
   		String requestURI = path + req.getPathInfo();
  @@ -363,6 +376,8 @@
   		    rd.forward(req.getFacade(), res.getFacade());
   		else
   		    rd.include(req.getFacade(), res.getFacade());
  +
  +		fixJDKContextClassLoader( originalCL );
   		return;
   	    }
   	    
  @@ -376,6 +391,7 @@
   		    context.log( "Class Not Found", ex );
   		    res.setStatus( 404 );
   		    contextM.handleError( req, res, null,  404 );
  +		    fixJDKContextClassLoader( originalCL );
   		    return;
   		}
   	    }
  @@ -425,9 +441,57 @@
   	    } else {
   		contextM.handleError( req, res, t, 0 );
   	    }
  +	} finally {
  +	    fixJDKContextClassLoader(originalCL );
  +	}
  +    }
  +
  +    static boolean haveContextClassLoader=true;
  +    static Class noParams[]=new Class[0];
  +    static Class clParam[]=new Class[1];
  +    static Object noObjs[]=new Object[0];
  +    static { clParam[0]=ClassLoader.class; }
  +
  +    /** Reflection trick to set the context class loader for JDK1.2, without
  +	braking JDK1.1.
  +
  +	This code can be commented out for 3.1 if it creates any problems -
  +	it should work.
  +
  +	XXX We need to find a better way to do that - maybe make it part of
  +	the ServletLoader interface.
  +     */
  +    ClassLoader fixJDKContextClassLoader( ClassLoader cl ) {
  +	if( cl==null ) return null;
  +	if( ! haveContextClassLoader ) return null;
  +	
  +	Thread t=Thread.currentThread();
  +	try {
  +	    java.lang.reflect.Method getCCL=t.getClass().getMethod("getContextClassLoader", noParams);
  +	    java.lang.reflect.Method setCCL=t.getClass().getMethod("setContextClassLoader", clParam) ;
  +	    if( (getCCL==null) || (setCCL==null) ) {
  +		haveContextClassLoader=false;
  +		return null;
  +	    }
  +	    ClassLoader old=( ClassLoader)getCCL.invoke( t, noObjs );
  +	    Object params[]=new Object[1];
  +	    params[0]=cl;
  +	    setCCL.invoke( t, params );
  +	    if( context.getDebug() > 5 ) context.log("Setting system loader " + old + " " + cl );
  +	    context.log("Setting system loader " + old + " " + cl );
  +	    
  +	    return old;
  +	} catch (NoSuchMethodException ex ) {
  +	    // we don't have the methods, don't try again
  +	    haveContextClassLoader=false;
  +	} catch( Exception ex ) {
  +	    haveContextClassLoader = false;
  +	    context.log( "Error setting jdk context class loader", ex );
   	}
  +	return null;
       }
   
  +    
       /** @deprecated
        */
       public void handleRequest(final HttpServletRequestFacade request,