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/08/02 05:50:33 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/request InvokerInterceptor.java JspInterceptor.java

costin      00/08/01 20:50:32

  Modified:    src/share/org/apache/tomcat/context
                        LoadOnStartupInterceptor.java WebXmlReader.java
               src/share/org/apache/tomcat/core Handler.java
               src/share/org/apache/tomcat/request InvokerInterceptor.java
                        JspInterceptor.java
  Added:       src/share/org/apache/tomcat/facade ServletWrapper.java
  Removed:     src/share/org/apache/tomcat/core ServletWrapper.java
  Log:
  Moved ServletWrapper to facade, simplified Handler.init ( SW overrides this
  anyway).
  
  This will allow us to later remove FacadeManager and simplify facade/core
  communication.
  
  Revision  Changes    Path
  1.18      +1 -0      jakarta-tomcat/src/share/org/apache/tomcat/context/LoadOnStartupInterceptor.java
  
  Index: LoadOnStartupInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/LoadOnStartupInterceptor.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- LoadOnStartupInterceptor.java	2000/08/02 02:17:07	1.17
  +++ LoadOnStartupInterceptor.java	2000/08/02 03:50:30	1.18
  @@ -63,6 +63,7 @@
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.core.Constants;
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.facade.ServletWrapper;
   import org.apache.tomcat.logging.*;
   import java.io.*;
   import java.net.*;
  
  
  
  1.30      +1 -0      jakarta-tomcat/src/share/org/apache/tomcat/context/WebXmlReader.java
  
  Index: WebXmlReader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/WebXmlReader.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- WebXmlReader.java	2000/08/02 02:17:07	1.29
  +++ WebXmlReader.java	2000/08/02 03:50:30	1.30
  @@ -4,6 +4,7 @@
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.xml.*;
   import org.apache.tomcat.logging.*;
  +import org.apache.tomcat.facade.ServletWrapper;
   import java.beans.*;
   import java.io.*;
   import java.io.IOException;
  
  
  
  1.10      +4 -17     jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java
  
  Index: Handler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- Handler.java	2000/08/02 02:17:11	1.9
  +++ Handler.java	2000/08/02 03:50:31	1.10
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java,v 1.9 2000/08/02 02:17:11 costin Exp $
  - * $Revision: 1.9 $
  - * $Date: 2000/08/02 02:17:11 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java,v 1.10 2000/08/02 03:50:31 costin Exp $
  + * $Revision: 1.10 $
  + * $Date: 2000/08/02 03:50:31 $
    *
    * ====================================================================
    *
  @@ -213,21 +213,8 @@
       {
   	try {
   	    if( initialized ) return;
  -	    if( ! (this instanceof ServletWrapper) ) {
  -		doInit();
  -		return;
  -	    }
  -	    
  -	    if( ! internal )
  -		contextM.doPreServletInit( context, this);
   	    doInit();
  -
  -	    // if an exception is thrown in init, no end interceptors will
  -	    // be called. that was in the origianl code J2EE used
  -
  -	    if( ! internal )
  -		contextM.doPostServletInit( context, this);
  -	    
  +	    return;
   	} catch( Exception ex ) {
   	    initialized=false;
   	}
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/facade/ServletWrapper.java
  
  Index: ServletWrapper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 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 acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", 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 apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * 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/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  package org.apache.tomcat.facade;
  
  import org.apache.tomcat.core.*;
  import org.apache.tomcat.util.*;
  import org.apache.tomcat.logging.*;
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  
  /**
   * Class used to represent a servlet inside a Context.
   * 
   * @author James Duncan Davidson [duncan@eng.sun.com]
   * @author Jason Hunter [jch@eng.sun.com]
   * @author James Todd [gonzo@eng.sun.com]
   * @author Harish Prabandham
   * @author costin@dnt.ro
   */
  public class ServletWrapper extends Handler {
  
      // servletName is stored in config!
      protected String servletName;
      protected String servletClassName; // required
      protected Class servletClass;
  
      protected Servlet servlet;
  
      // facade
      protected ServletConfig configF;
  
      // Jsp pages
      private String path = null;
  
      // optional informations
      protected String description = null;
  
      // If init() fails, this will keep the reason.
      // init may be called when the servlet starts, but we need to
      // report the error later, to the client
      Exception unavailable=null;
      long unavailableTime=-1;
      
      // Usefull info for class reloading
      protected boolean isReloadable = false;
      // information + make sure destroy is called when no other servlet
      // is running ( this have to be revisited !) 
      protected long lastAccessed;
      protected int serviceCount = 0;
      
      int loadOnStartup=0;
  
      Hashtable securityRoleRefs=new Hashtable();
  
      public ServletWrapper() {
      }
  
      public void setContext( Context context) {
  	super.setContext( context );
  	isReloadable=context.getReloadable();
          configF = context.getFacadeManager().createServletConfig( this );
      }
  
      public String toString() {
  	return name + "(" + servletClassName + "/" + path + ")";
      }
      
      // -------------------- Servlet specific properties 
      public void setLoadOnStartUp( int level ) {
  	loadOnStartup=level;
      }
  
      public void setLoadOnStartUp( String level ) {
  	loadOnStartup=new Integer(level).intValue();
      }
  
      public int getLoadOnStartUp() {
  	return loadOnStartup;
      }
      
      void setReloadable(boolean reloadable) {
  	isReloadable = reloadable;
      }
  
      public String getName() {
  	return getServletName();
      }
      
      public String getServletName() {
  	if(name!=null) return name;
  	return path;
      }
  
      public void setServletName(String servletName) {
          this.servletName=servletName;
  	name=servletName;
      }
  
      public String getServletDescription() {
          return this.description;
      }
  
      public void setDescription( String d ) {
  	description=d;
      }
      
      public void setServletDescription(String description) {
          this.description = description;
      }
  
      public String getServletClass() {
          return this.servletClassName;
      }
  
      public String getServletClassName() {
          return this.servletClassName;
      }
  
      public void setServletClass(String servletClassName) {
  	if( name==null ) name=servletClassName;
  	this.servletClassName = servletClassName;
  	servlet=null; // reset the servlet, if it was set
  	servletClass=null;
  	initialized=false;
      }
  
      public void reload() {
  	if( initialized ) {
  	    try {
  		destroy();
  	    } catch(Exception ex ) {
  		log( "Error in destroy ", ex );
  	    }
  	}
  
  	if( servletClassName != null ) {
  	    // I can survive reload
  	    servlet=null;
  	    servletClass=null;
  	}
  	initialized=false;
      }
      
      /** Security Role Ref represent a mapping between servlet role names and
       *  server roles
       */
      public void addSecurityMapping( String name, String role,
  				    String description ) {
  	securityRoleRefs.put( name, role );
      }
  
      public String getSecurityRole( String name ) {
  	return (String)securityRoleRefs.get( name );
      }
  
      // -------------------- Jsp specific code
      // Will go in JspHandler
      
      public String getPath() {
          return this.path;
      }
  
      public void setPath(String path) {
          this.path = path;
      }
  
      // -------------------- 
  
      public Servlet getServlet() {
  	if(servlet==null) {
  	    try {
  		loadServlet();
  	    } 	catch( Exception ex ) {
  		log("in loadServlet()", ex);
  	    }
  	}
  	return servlet;
      }
  
      protected void doDestroy() throws TomcatException {
  	synchronized (this) {
  	    // Fancy sync logic is to make sure that no threads are in the
  	    // handlerequest when this is called and, furthermore, that
  	    // no threads go through handle request after this method starts!
  	    // Wait until there are no outstanding service calls,
  	    // or until 30 seconds have passed (to avoid a hang)
  		
  	    //XXX I don't think it works ( costin )
  	    
  	    // XXX Move it to an interceptor!!!!
  	    while (serviceCount > 0) {
  		try {
  		    wait(30000);
  		    break;
  		} catch (InterruptedException e) { }
  	    }
  
  	    try {
  		if( servlet!=null) 
  		    servlet.destroy();
  	    } catch(Exception ex) {
  		// Should never come here...
  		log( "Error in destroy ", ex );
  	    }
  	}
      }
  
      /** Load and init a the servlet pointed by this wrapper
       */
      private void loadServlet()
  	throws ClassNotFoundException, InstantiationException,
  	IllegalAccessException
      {
  	// XXX Move this to an interceptor, so it will be configurable.
  	// ( and easier to read )
  	// 	log("LoadServlet " + servletClass + " "
  	// 			   + servletClassName);
  	if (servletClass == null) {
  	    if (servletClassName == null) {
  		throw new IllegalStateException("Can't happen - classname "
  						+ "is null, who added this ?");
  	    }
  	    servletClass=context.getClassLoader().loadClass(servletClassName);
  	}
  	
  	servlet = (Servlet)servletClass.newInstance();
  
  	// hack for internal servlets
  	if( ! servletClassName.startsWith("org.apache.tomcat") ) return;
      }
  
      /** Override Handler's init - load the servlet before calling
  	and interceptor
      */
      public void init()
      	throws Exception
     {
  	// make sure the servlet is loaded before calling preInit
  	// Jsp case - maybe another Jsp engine is used
  	if( servlet==null && path != null &&  servletClassName == null) {
  	    log("Calling handleJspInit " + servletClassName);
  	    handleJspInit();
  	}
  	// Will throw exception if it can't load, let upper
  	// levels handle this
  	//	try {
  	if( servlet==null ) loadServlet();
  	//	} catch( ClassNotFoundException ex ) {
  	//	} catch( InstantiationException ex ) {
  	//} catch( IllegalStateException ex ) {
  	//}
  	
  	// Call pre, doInit and post
  	contextM.doPreServletInit( context, this);
  	doInit();
  	
  	// if an exception is thrown in init, no end interceptors will
  	// be called. that was in the origianl code J2EE used
  	
  	contextM.doPostServletInit( context, this);
      }
  
      protected void doInit()
  	throws Exception
      {
  	// The servlet is loaded and not null - otherwise init()
  	// throws exception
  	try {
  	    // if multiple threads will call the same servlet at once,
  	    // we should have only one init 
  	    synchronized( this ) {
  		// we may have 2 threads entering doInit,
  		// the first one may init the servlet
  		if( initialized )
  		    return;
  		final Servlet sinstance = servlet;
  		final ServletConfig servletConfig = configF;
  		
  		// init - only if unavailable was null or
  		// unavailable period expired
  		servlet.init(servletConfig);
  		initialized=true;
  	    }
  	} catch( UnavailableException ex ) {
  	    unavailable=ex;
  	    unavailableTime=System.currentTimeMillis();
  	    unavailableTime += ex.getUnavailableSeconds() * 1000;
  	} catch( Exception ex ) {
  	    unavailable=ex;
  	}
      }
  
      /** Override service to hook reloading - it can be done in a clean
  	interceptor. It also hooks jsp - we should have a separate
  	JspHandler
      */
      public void service(Request req, Response res) 
      {
  	// <servlet><jsp-file> case
  	if( path!=null ) {
  	    if( path.startsWith("/"))
  		req.setAttribute( "javax.servlet.include.request_uri",
  				  req.getContext().getPath()  + path );
  	    else
  		req.setAttribute( "javax.servlet.include.request_uri",
  				  req.getContext().getPath()  + "/" + path );
  	    req.setAttribute( "javax.servlet.include.servlet_path", path );
  	}
  
  	if( unavailable!=null  ) {
  	    // Don't load if Unavailable timer is in place
  	    if(  stillUnavailable() ) {
  		handleUnavailable( req, res );
  		initialized=false;
  		return;
  	    }
  	    unavailable=null;// timer expired
  	}
  
  	// called only if unavailable==null or timer expired.
  	// will do an init
  	super.service( req, res );
      }
  
      protected void doService(Request req, Response res)
  	throws Exception
      {
  	// We are initialized and fine
  	if (servlet instanceof SingleThreadModel) {
  	    synchronized(servlet) {
  		servlet.service(req.getFacade(), res.getFacade());
  	    }
  	} else {
  	    servlet.service(req.getFacade(), res.getFacade());
  	}
      }
  
      // -------------------- Jsp hooks
      // <servlet><jsp-file> case - we know it's a jsp
      void handleJspInit() {
  	// XXX Jsp Servlet is initialized, the servlet is not generated -
  	// we can't hook in! It's jspServet that has to pass the config -
  	// but it can't so easily, plus  it'll have to hook in.
  	// I don't think that ever worked anyway - and I don't think
  	// it can work without integrating Jsp handling into tomcat
  	// ( using interceptor )
  	ServletWrapper jspServletW = (ServletWrapper)context.getServletByName("jsp");
  	servletClassName = jspServletW.getServletClass();
      }
      
  
      // -------------------- Unavailable --------------------
      /** Check if we can try again an init
       */
      private boolean stillUnavailable() {
  	// we have a timer - maybe we can try again - how much
  	// do we have to wait - (in mSec)
  	long moreWaitTime=unavailableTime - System.currentTimeMillis();
  	if( unavailableTime > 0 && ( moreWaitTime < 0 )) {
  	    // we can try again
  	    unavailable=null;
  	    unavailableTime=-1;
  	    log(getServletName() + " unavailable time expired," +
  			" try again ");
  	    return false;
  	} else {
  	    return true;
  	}
      }
      
      /** Send 503. Should be moved in ErrorHandling
       */
      private void handleUnavailable( Request req, Response res ) {
  	if( unavailable instanceof UnavailableException ) {
  	    int unavailableTime = ((UnavailableException)unavailable).
  		getUnavailableSeconds();
  	    if( unavailableTime > 0 ) {
  		res.setHeader("Retry-After",
  			      Integer.toString(unavailableTime));
  	    }
  	}
  
  	String msg=unavailable.getMessage();
  	long moreWaitTime=unavailableTime - System.currentTimeMillis();
  	log( "Error in " + getServletName() +
  		     "init(), error happened at " +
  		     unavailableTime + " wait " + moreWaitTime +
  		     " : " + msg, unavailable);
  	req.setAttribute("javax.servlet.error.message", msg );
  	res.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE); // 503
  	contextM.handleStatus( req, res,
  			       HttpServletResponse.SC_SERVICE_UNAVAILABLE );
  	return;
      }
  
  }
  
  
  
  1.7       +1 -0      jakarta-tomcat/src/share/org/apache/tomcat/request/InvokerInterceptor.java
  
  Index: InvokerInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/InvokerInterceptor.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- InvokerInterceptor.java	2000/08/02 02:17:27	1.6
  +++ InvokerInterceptor.java	2000/08/02 03:50:31	1.7
  @@ -60,6 +60,7 @@
   
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.core.*;
  +import org.apache.tomcat.facade.ServletWrapper;
   import org.apache.tomcat.facade.*;
   import org.apache.tomcat.logging.*;
   import org.apache.tomcat.core.Constants;
  
  
  
  1.7       +1 -0      jakarta-tomcat/src/share/org/apache/tomcat/request/JspInterceptor.java
  
  Index: JspInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/JspInterceptor.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- JspInterceptor.java	2000/08/02 02:17:27	1.6
  +++ JspInterceptor.java	2000/08/02 03:50:32	1.7
  @@ -71,6 +71,7 @@
   import org.apache.tomcat.logging.Logger;
   import org.apache.jasper.compiler.Compiler;
   import org.apache.tomcat.core.*;
  +import org.apache.tomcat.facade.ServletWrapper;
   
   /**
    * Plug in the JSP engine (a.k.a Jasper)!