costin      00/12/12 14:33:04

  Modified:    src/facade22/org/apache/tomcat/facade
                        Servlet22Interceptor.java ServletHandler.java
               src/facade22/org/apache/tomcat/modules/facade22
                        LoadOnStartupInterceptor.java
               src/share/org/apache/tomcat/core Handler.java
  Log:
  Another step in Handler/ServletWrapper refactoring - moved init, destroy
  and all related code to ServletHandler.
  
  The big advantage is that now Handler is very simple, it deals only with
  service() ( and we go back to the Apache/IIS/NES model where the handler
  is a simple object ). All lifecycle ( init, etc) is present in the interceptor,
  and duplicating it in Handler was confusing and resulted in many errors.
  
  The Handler is a part of the extension mechanism of tomcat - a module
  ( Interceptor ) can define a number of handlers ( like StaticHandler,
  ServletHandler) to generate the output ( either directly or via another
  mechanism - like servlets, jsps )
  
  I think this is the right direction, please review it and send any comments.
  ( there are few more simplifications, but this commit has only the code
  move and associated fixes )
  
  Revision  Changes    Path
  1.8       +3 -1      
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/Servlet22Interceptor.java
  
  Index: Servlet22Interceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/Servlet22Interceptor.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Servlet22Interceptor.java 2000/12/12 20:21:21     1.7
  +++ Servlet22Interceptor.java 2000/12/12 22:32:54     1.8
  @@ -116,9 +116,11 @@
        while (enum.hasMoreElements()) {
            String key = (String)enum.nextElement();
            Handler wrapper = ctx.getServletByName( key );
  +         if( ! (wrapper instanceof ServletHandler) )
  +             continue;
            ctx.removeServletByName( key );
            try {
  -             wrapper.destroy();
  +             ((ServletHandler)wrapper).destroy();
            } catch(Exception ex ) {
                ctx.log( "Error in destroy ", ex);
            }
  
  
  
  1.2       +162 -1    
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletHandler.java
  
  Index: ServletHandler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletHandler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ServletHandler.java       2000/12/12 20:21:24     1.1
  +++ ServletHandler.java       2000/12/12 22:32:54     1.2
  @@ -87,13 +87,30 @@
    */
   public final class ServletHandler extends Handler {
   
  +    /** 
  +     * If init() fails or preInit() detects the handler is still
  +     * unavailable.
  +     */
  +    public static final int STATE_DELAYED_INIT=2;
  +
  +    /** The handler has been succesfully initialized and is ready to
  +     * serve requests. If the handler is not in this state a 500 error
  +     * should be reported. ( customize - may be 404 )
  +     * To ADDED by calling destroy()
  +     * FROM ADDED by calling init()
  +     */
  +    public static final int STATE_READY=3;
  +
  +    // -------------------- Properties --------------------
  +    
       // extra informations - if the servlet is declared in web.xml
       private ServletInfo sw;
   
       private String servletClassName;
  +    private String path;
       protected Class servletClass;
       protected Servlet servlet;
  -
  +    
       // If init() fails, Handler.errorException will hold the reason.
       // In the case of an UnavailableException, this field will hold
       // the expiration time if UnavailableException is not permanent.
  @@ -135,6 +152,122 @@
           return servletClassName;
       }
   
  +    // -------------------- Init/destroy --------------------
  +    // from Handler
  +
  +    /** Destroy a handler, and notify all the interested interceptors
  +     */
  +    public final void destroy() {
  +     if ( state!=STATE_READY ) {
  +         // reset exception
  +         errorException = null;
  +         return;// already destroyed or not init.
  +     }
  +     setState( STATE_ADDED );
  +
  +     // XXX post will not be called if any error happens in destroy.
  +     // That's how tomcat worked before - I think it's a bug !
  +     try {
  +         doDestroy();
  +     } catch( Exception ex ) {
  +         log( "Error during destroy ", ex );
  +     }
  +     
  +
  +     errorException=null;
  +    }
  +
  +
  +    /** Call the init method, and notify all interested listeners.
  +     *  This is a final method to insure consistent behavior on errors.
  +     *  It also saves handlers from dealing with synchronization issues.
  +     */
  +    public final void init()
  +    {
  +     // we use getState() as a workaround for bugs in VMs
  +     
  +     if( getState() == STATE_READY || getState() == STATE_DISABLED )
  +         return;
  +
  +     synchronized( this ) {
  +         // check again - if 2 threads are in init(), the first one will
  +         // init and the second will enter the sync block after that
  +         if( getState() == STATE_READY ) 
  +             return;
  +
  +         // if exception present, then we were sync blocked when first
  +         // init() failed or an interceptor set an inital exeception
  +         // A different thread got an error in init() - throw
  +         // the same error.
  +         if (getState() == STATE_DISABLED )
  +             return; //throw errorException;
  +
  +         try {
  +             // special preInit() hook
  +             preInit();
  +             // preInit may either throw exception or setState DELAYED_INIT
  +         } catch( Exception ex ) {
  +             // save error, assume permanent
  +             log("Exception in preInit  " + ex.getMessage(), ex );
  +             setErrorException(ex);
  +             setState(STATE_DISABLED);
  +             return;
  +         }
  +         
  +         // we'll try again later 
  +         if( getState() == STATE_DELAYED_INIT ||
  +             getState()==STATE_DISABLED ) { // or disabled 
  +             return;
  +         }
  +         // preInit have no exceptions and doesn't delay us
  +         // We can run init hooks and init
  +
  +         // Call pre, doInit and post
  +         BaseInterceptor cI[]=context.getContainer().getInterceptors();
  +         for( int i=0; i< cI.length; i++ ) {
  +             try {
  +                 cI[i].preServletInit( context, this );
  +             } catch( TomcatException ex) {
  +                 // log, but ignore.
  +                 log("preServletInit" , ex);
  +             }
  +         }
  +             
  +         try {
  +             doInit();
  +             // if success, we are ready to serve
  +         } catch( Exception ex ) {
  +             // save error, assume permanent
  +             log("Exception in init  " + ex.getMessage(), ex );
  +             setErrorException(ex);
  +             state=STATE_DISABLED;
  +         }
  +         
  +         for( int i=0; i< cI.length; i++ ) {
  +             try {
  +                 cI[i].postServletInit( context, this );
  +             } catch( TomcatException ex) {
  +                 log("postServletInit" , ex);
  +             }
  +         }
  +
  +         // Now that both pre/post hooks have been called, the
  +         // servlet is ready to serve.
  +
  +         // We are still in the sync block, that means other threads
  +         // are waiting for this to be over.
  +
  +         // if no error happened and if doInit didn't put us in
  +         // a special state, we are ready
  +         if( state!=STATE_DISABLED &&
  +             getErrorException() != null ) {
  +             state=STATE_READY;
  +         }
  +     }
  +    }
  +
  +    
  +    
       // -------------------- --------------------
   
       public void reload() {
  @@ -255,6 +388,32 @@
        // init() will deal with them.
       }
   
  +    // Overrides the default handler
  +    public void service ( Request req, Response res ) {
  +     if( state!=STATE_READY ) {
  +         if( state!= STATE_DISABLED ) {
  +             init();
  +         }
  +         if( state== STATE_DISABLED ) {
  +             // the init failed because of an exception
  +             Exception ex=getErrorException();
  +             // save error state on request and response
  +             saveError( req, res, ex );
  +             // if in included, defer handling to higher level
  +             if (res.isIncluded()) return;
  +             // handle init error since at top level
  +             if( ex instanceof ClassNotFoundException )
  +                 contextM.handleStatus( req, res, 404 );
  +             else
  +                 contextM.handleError( req, res, ex );
  +             return;
  +         } 
  +     }
  +
  +     super.service( req, res );
  +    }
  +
  +    
       protected void doService(Request req, Response res)
        throws Exception
       {
  @@ -366,4 +525,6 @@
        // still unavailable
        return false;
       }
  +
  +
   }
  
  
  
  1.2       +1 -1      
jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/LoadOnStartupInterceptor.java
  
  Index: LoadOnStartupInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/LoadOnStartupInterceptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- LoadOnStartupInterceptor.java     2000/12/12 20:21:30     1.1
  +++ LoadOnStartupInterceptor.java     2000/12/12 22:32:57     1.2
  @@ -135,7 +135,7 @@
                            getPath() != null ) {
                            loadJsp( ctx, result );
                        } else {
  -                         result.init();
  +                         ((ServletHandler)result).init();
                        }
                    } catch (Exception ee) {
                        String msg = sm.getString("context.loadServlet.e",
  
  
  
  1.28      +5 -202    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.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- Handler.java      2000/12/12 20:21:38     1.27
  +++ Handler.java      2000/12/12 22:33:02     1.28
  @@ -150,20 +150,6 @@
        */
       public static final int STATE_ADDED=1;
   
  -    /** 
  -     * If init() fails or preInit() detects the handler is still
  -     * unavailable.
  -     */
  -    public static final int STATE_DELAYED_INIT=2;
  -
  -    /** The handler has been succesfully initialized and is ready to
  -     * serve requests. If the handler is not in this state a 500 error
  -     * should be reported. ( customize - may be 404 )
  -     * To ADDED by calling destroy()
  -     * FROM ADDED by calling init()
  -     */
  -    public static final int STATE_READY=3;
  -
       /** Handler is unable to perform - any attempt to use it should
        *  report an internal error. This is the result of an internal
        *  exception or an error in init()
  @@ -172,21 +158,16 @@
        */
       public static final int STATE_DISABLED=4;
   
  -    
  -
       // -------------------- Properties --------------------
       protected Context context;
       protected ContextManager contextM;
       
       protected String name;
  +    protected int state=STATE_NEW;
   
  -    private int state=STATE_NEW;
  -    
       // who creates the servlet definition
       protected int origin;
   
  -    protected String path;
  -
       protected Exception errorException=null;
       
       // Debug
  @@ -220,6 +201,8 @@
        return context;
       }
   
  +    // -------------------- configuration --------------------
  +
       public int getState() {
        return state;
       }
  @@ -228,8 +211,6 @@
        this.state=i;
       }
       
  -    // -------------------- configuration --------------------
  -
       public final String getName() {
        return name;
       }
  @@ -276,131 +257,8 @@
        return errorException;
       }
   
  -//     // -------------------- Jsp specific code
  -    
  -//     public String getPath() {
  -//         return this.path;
  -//     }
  -
  -//     public void setPath(String path) {
  -//         this.path = path;
  -//   if( name==null )
  -//       name=path; // the path will serve as servlet name if not set
  -//     }
  -
       // -------------------- Methods --------------------
   
  -    /** Destroy a handler, and notify all the interested interceptors
  -     */
  -    public final void destroy() {
  -     if ( state!=STATE_READY ) {
  -         // reset exception
  -         errorException = null;
  -         return;// already destroyed or not init.
  -     }
  -     setState( STATE_ADDED );
  -
  -     // XXX post will not be called if any error happens in destroy.
  -     // That's how tomcat worked before - I think it's a bug !
  -     try {
  -         doDestroy();
  -     } catch( Exception ex ) {
  -         log( "Error during destroy ", ex );
  -     }
  -     
  -
  -     errorException=null;
  -    }
  -
  -
  -    /** Call the init method, and notify all interested listeners.
  -     *  This is a final method to insure consistent behavior on errors.
  -     *  It also saves handlers from dealing with synchronization issues.
  -     */
  -    public final void init()
  -    {
  -     // we use getState() as a workaround for bugs in VMs
  -     
  -     if( getState() == STATE_READY || getState() == STATE_DISABLED )
  -         return;
  -
  -     synchronized( this ) {
  -         // check again - if 2 threads are in init(), the first one will
  -         // init and the second will enter the sync block after that
  -         if( getState() == STATE_READY ) 
  -             return;
  -
  -         // if exception present, then we were sync blocked when first
  -         // init() failed or an interceptor set an inital exeception
  -         // A different thread got an error in init() - throw
  -         // the same error.
  -         if (getState() == STATE_DISABLED )
  -             return; //throw errorException;
  -
  -         try {
  -             // special preInit() hook
  -             preInit();
  -             // preInit may either throw exception or setState DELAYED_INIT
  -         } catch( Exception ex ) {
  -             // save error, assume permanent
  -             log("Exception in preInit  " + ex.getMessage(), ex );
  -             setErrorException(ex);
  -             setState(STATE_DISABLED);
  -             return;
  -         }
  -         
  -         // we'll try again later 
  -         if( getState() == STATE_DELAYED_INIT ||
  -             getState()==STATE_DISABLED ) { // or disabled 
  -             return;
  -         }
  -         // preInit have no exceptions and doesn't delay us
  -         // We can run init hooks and init
  -
  -         // Call pre, doInit and post
  -         BaseInterceptor cI[]=context.getContainer().getInterceptors();
  -         for( int i=0; i< cI.length; i++ ) {
  -             try {
  -                 cI[i].preServletInit( context, this );
  -             } catch( TomcatException ex) {
  -                 // log, but ignore.
  -                 log("preServletInit" , ex);
  -             }
  -         }
  -             
  -         try {
  -             doInit();
  -             // if success, we are ready to serve
  -         } catch( Exception ex ) {
  -             // save error, assume permanent
  -             log("Exception in init  " + ex.getMessage(), ex );
  -             setErrorException(ex);
  -             state=STATE_DISABLED;
  -         }
  -         
  -         for( int i=0; i< cI.length; i++ ) {
  -             try {
  -                 cI[i].postServletInit( context, this );
  -             } catch( TomcatException ex) {
  -                 log("postServletInit" , ex);
  -             }
  -         }
  -
  -         // Now that both pre/post hooks have been called, the
  -         // servlet is ready to serve.
  -
  -         // We are still in the sync block, that means other threads
  -         // are waiting for this to be over.
  -
  -         // if no error happened and if doInit didn't put us in
  -         // a special state, we are ready
  -         if( state!=STATE_DISABLED &&
  -             getErrorException() != null ) {
  -             state=STATE_READY;
  -         }
  -     }
  -    }
  -
       /** Call the service method, and notify all listeners
        *
        * @exception Exception if an error happens during handling of
  @@ -415,28 +273,8 @@
        *  Tomcat should be able to handle and log any other exception ( including
        *  runtime exceptions )
        */
  -    public final void service(Request req, Response res)
  +    public void service(Request req, Response res)
       {
  -     if( state!=STATE_READY ) {
  -         if( state!= STATE_DISABLED ) {
  -             init();
  -         }
  -         if( state== STATE_DISABLED ) {
  -             // the init failed because of an exception
  -             Exception ex=getErrorException();
  -             // save error state on request and response
  -             saveError( req, res, ex );
  -             // if in included, defer handling to higher level
  -             if (res.isIncluded()) return;
  -             // handle init error since at top level
  -             if( ex instanceof ClassNotFoundException )
  -                 contextM.handleStatus( req, res, 404 );
  -             else
  -                 contextM.handleError( req, res, ex );
  -             return;
  -         } 
  -     }
  -     
        BaseInterceptor reqI[]=
            req.getContainer().getInterceptors(Container.H_preService);
        for( int i=0; i< reqI.length; i++ ) {
  @@ -469,14 +307,10 @@
       }
   
       // -------------------- methods you can override --------------------
  -
  -    protected void handleInitError( Throwable t ) {
  -
  -    }
       
       protected void handleServiceError( Request req, Response res, Throwable t )
       {
  -
  +     // XXX TODO
       }
       
       /** Reload notification. This hook is called whenever the
  @@ -484,38 +318,7 @@
        */
       public void reload() {
       }
  -        
  -    /** This method will be called when the handler
  -     *       is removed ( by admin or timeout ).
  -     */
  -    protected void doDestroy() throws Exception {
  -
  -    }
  -
  -    /** Special hook called before init and init hooks. 
  -     *
  -     *  This hook will set the state of the handler for the init() hooks
  -     * ( for example load the servlet class, other critical preparations ).
  -     *  If it fails, the servlet will be disabled and no other call will
  -     *  succed.
  -     *  The hook can also delay initialization ( put handler in  DELAY_INIT
  -     *  state ). The application will be unavailable ( no service will be
  -     *  called ), and preInit will be called to check if the state changed.
  -     *  ( this can be used to implement UnavailableException )
  -     *
  -     */
  -    protected void preInit() throws Exception {
  -
  -    }
       
  -    /** Initialize the handler. Handler can override this
  -     *       method to initialize themself.
  -     */
  -    protected void doInit() throws Exception
  -    {
  -     
  -    }
  -
       /** This is the actual content generator. Can't be called
        *  from outside.
        *
  
  
  

Reply via email to