costin      00/12/11 16:42:50

  Modified:    src/facade22/org/apache/tomcat/facade
                        Servlet22Interceptor.java ServletWrapper.java
                        WebXmlReader.java
               src/facade22/org/apache/tomcat/modules/facade22
                        JspInterceptor.java
               src/share/org/apache/tomcat/context ErrorHandler.java
               src/share/org/apache/tomcat/core Context.java Handler.java
               src/share/org/apache/tomcat/request AccessInterceptor.java
                        StaticInterceptor.java
               src/share/org/apache/tomcat/startup Main.java
  Log:
  First round of refactoring for Handler/ServletWrapper. Reorganized the code
  to make sure the right order of calls in the right state is enforced.
  
  It seems that Handler is still too complex, and a lot of servlet-specific code
  ( like handling of init, UnavailableException, etc) need to be moved in
  the right place ( ServletWrapper). The problem is that ServletWrapper is too
  complex.
  
  I'll start cleaning ServletWrapper and then move init/destroy - Handler will
  then be a very simple and maintainable class. I need your review on this one,
  please send comments if you find any problem.
  
  Revision  Changes    Path
  1.6       +4 -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.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Servlet22Interceptor.java 2000/11/02 21:51:39     1.5
  +++ Servlet22Interceptor.java 2000/12/12 00:42:40     1.6
  @@ -144,7 +144,10 @@
            ServletWrapper sw=new ServletWrapper();
            sw.setName( hN );
            sw.setContext( ct.getContext() );
  -         log( "Create handler ");
  +         // *.jsp -> jsp is a legacy default mapping  
  +         if( ! "jsp".equals(hN) ) {
  +             log( "Create handler " + hN);
  +         }
            ct.setHandler(sw);
            ct.getContext().addServlet(  sw );
        }
  
  
  
  1.14      +124 -143  
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletWrapper.java
  
  Index: ServletWrapper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletWrapper.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- ServletWrapper.java       2000/12/08 23:18:29     1.13
  +++ ServletWrapper.java       2000/12/12 00:42:40     1.14
  @@ -124,8 +124,19 @@
       public String toString() {
        if( path==null )
            return "Servlet " + name + "(" + servletClassName  + ")";
  -     return "Jsp " + name + "(" + path + ")";
  +     return "Jsp " + name + "(" + path + "/" + servletClassName +  ")";
       }
  +
  +    // -------------------- Configuration hook
  +
  +    /** This method can called to add the servlet to the web application.
  +     * ( typlically used from the config - WebXmlReader ).
  +     */
  +    public void addServlet(Context ctx) throws TomcatException {
  +     context=ctx;
  +     //      System.out.println("Adding servlet " + this );
  +     context.addServlet( this );
  +    }
       
       // -------------------- Servlet specific properties 
       public void setLoadOnStartUp( int level ) {
  @@ -170,17 +181,21 @@
       }
   
       public String getServletClass() {
  -        return this.servletClassName;
  +        return getServletClassName();
       }
   
       public String getServletClassName() {
  -        return this.servletClassName;
  +     if( servletClassName == null )
  +         servletClassName=name;
  +        return servletClassName;
       }
   
       public void setServletClassName(String servletClassName) {
        servlet=null; // reset the servlet, if it was set
        servletClass=null;
        this.servletClassName=servletClassName;
  +     if( debug>0 && path!=null)
  +         log( "setServletClassName for jsp " + servletClassName);
       }
       public void setServletClass(String servletClassName) {
        setServletClassName(servletClassName);
  @@ -191,7 +206,8 @@
        if ( ex != null ) {
            if ( ex instanceof UnavailableException &&
                    ! ((UnavailableException)ex).isPermanent()) {
  -             // make updated UnavailableException, reporting a minimum of 1 second
  +             // make updated UnavailableException, reporting a minimum
  +             // of 1 second
                int secs=1;
                long moreWaitTime=unavailableTime - System.currentTimeMillis();
                if( moreWaitTime > 0 )
  @@ -204,7 +220,7 @@
   
   
       public void reload() {
  -     if( initialized ) {
  +     if( getState()==STATE_READY ) {
            try {
                destroy();
            } catch(Exception ex ) {
  @@ -212,12 +228,12 @@
            }
        }
   
  -     if( servletClassName != null ) {
  +     if( getServletClassName() != null ) {
            // I can survive reload
            servlet=null;
            servletClass=null;
        }
  -     initialized=false;
  +     setState( STATE_ADDED );
       }
       
       /** Security Role Ref represent a mapping between servlet role names and
  @@ -247,7 +263,9 @@
       // -------------------- 
   
       public Servlet getServlet() {
  +     
        if(servlet==null) {
  +         System.out.println("XXX getServlet for un-loaded servlet ");
            try {
                loadServlet();
            }   catch( Exception ex ) {
  @@ -303,116 +321,80 @@
        }
       }
   
  +    // Special hook
  +    protected void preInit() throws Exception
  +    {
  +     if( debug > 0 )
  +         log( "preInit " + servlet + " " + path + " " + servletClassName);
  +
  +     // Deal with Unavailable errors
  +     if( ! checkErrorExpired() ) {
  +         // init can't proceed
  +         setState( STATE_DELAYED_INIT );
  +         return;
  +     }
  +     
  +     // For JSPs we rely on JspInterceptor to set the servlet class name.
  +     // We make no distinction between servlets and jsps.
  +     loadServlet();
  +    }
  +
       /** 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( debug>0)
  +         log("LoadServlet " + name + " " + servletName + " " +
  +             servletClass + " " + servletClassName);
   
        // default
        if( servletClassName==null )
  -         servletClassName=servletName;
  +         servletClassName=name;
        
        if (servletClass == null) {
  -         if (servletClassName == null) {
  -             // It happens :-(
  -             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
  -   {
  -     // if initialized, then we were sync blocked when first init() succeeded
  -     if( initialized ) return;
  -     // if exception present, then we were sync blocked when first init() failed
  -     // or an interceptor set an inital exeception
  -     // in the latter case, preServletInit() and postServletInit() interceptors
  -     // don't get called
  -     if ( isExceptionPresent() ) return;
  -
  -       // make sure the servlet is loaded before calling preInit
  -     // Jsp case - maybe another Jsp engine is used
  -
  -     if( servlet==null && path != null && ! jspServletInitialized ) {
  -         //      log("Calling handleJspInit " + servletClassName);
  -         // dual mode
  -         handleJspInit();
  -         jspServletInitialized=true;
  -     }
   
  -     if( servlet==null ) {
  -         // try to load servlet, save exception if one occurs
  -         try {
  -             loadServlet();
  -         } catch ( Exception ex ) {
  -             // save init exception
  -             setErrorException( ex );
  -             setExceptionPermanent( true );
  -             return;
  -         }
  -     }
  -
  -     // 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("preServletInit" , ex);
  -         }
  -     }
  -
  -     doInit();
  -
  -     // doInit() catches exceptions, so post interceptors are always called  
  -     for( int i=0; i< cI.length; i++ ) {
  -         try {
  -             cI[i].postServletInit( context, this );
  -         } catch( TomcatException ex) {
  -             log("postServletInit" , ex);
  -         }
  -     }
  +    public ServletConfig getServletConfig() {
  +     if( configF==null )
  +         configF=new ServletConfigImpl( this );
  +     return configF;
       }
  -
  +    
       protected void doInit()
        throws Exception
       {
        isReloadable=context.getReloadable();
           configF = new ServletConfigImpl(this);
   
  -     // ASSERT synchronized at higher level, initialized must be false
        try {
            final Servlet sinstance = servlet;
            final ServletConfig servletConfig = configF;
            servlet.init(servletConfig);
  -         initialized=true;
        } catch( UnavailableException ex ) {
  -         setServletUnavailable( ex );
  -         servlet=null;
  -     } catch( Exception ex ) {
  -         // other init exceptions are treated as permanent
  -         // XXX need a context setting for unavailable time
  -         setErrorException(ex);
  -         setExceptionPermanent(true);
  +         // Implement the "UnavailableException" specification
  +         // servlet exception state
  +         setErrorException( ex );
  +         if ( ex.isPermanent() ) {
  +             setState( STATE_DISABLED );
  +         } else {
  +             setState( STATE_DELAYED_INIT );
  +             setServletUnavailable( ex );
  +         }
            servlet=null;
  +         throw ex;
  +         // it's a normal exception, servlet will
  +         // not be initialized.
        }
  +
  +     // other exceptions are just thrown -
  +     // init() will deal with them.
       }
   
       protected void doService(Request req, Response res)
  @@ -428,11 +410,16 @@
                                  req.getContext().getPath()  + "/" + path );
            req.setAttribute( "javax.servlet.include.servlet_path", path );
        }
  +
   
  -     // if servlet is not available
  -     if ( isExceptionPresent() ) {
  -         // get if error has expired
  -         checkErrorExpired( req, res );
  +     // if unavailable
  +     if( ! checkErrorExpired() ) {
  +         // if error still present
  +         Exception ex=getErrorException();
  +         if( ex!=null ) {
  +             // save error state on request and response
  +             saveError( req, res, ex );
  +         }
            // if we have an error on this request
            if ( req.isExceptionPresent()) {
                // if in included, defer handling to higher level
  @@ -441,8 +428,7 @@
                // otherwise handle error
                contextM.handleError( req, res, getErrorException());
            }
  -         context.log(getServletName() +
  -                     " unavailable time expired, trying again ");
  +         return; // we can't handle it
        }
   
        // Get facades - each req have one facade per context
  @@ -463,26 +449,30 @@
            req.setFacade( reqF );
            res.setFacade( resF );
        }
  +
  +     if( servlet==null ) {
  +         System.out.println("XXX servlet==null " + getState() );
  +         loadServlet();
  +     }
        
        try {
            doService( reqF, resF );
  -     } catch ( Exception ex ) {
  -         // support for UnavailableException
  -         if ( ex instanceof UnavailableException ) {
  -             // if error not set
  -             if ( ! isExceptionPresent() ) {
  -                 synchronized(this) {
  -                     if ( ! isExceptionPresent() ) {
  -                         setServletUnavailable( (UnavailableException)ex );
  -                         // XXX if the UnavailableException is permanent we are 
supposed
  -                         // to destroy the servlet.  Synchronization of this 
destruction
  -                         // needs review before adding this.
  -                     }
  +     } catch ( UnavailableException ex ) {
  +         if ( ex.isPermanent() ) {
  +             setState( STATE_DISABLED );
  +         } else {
  +             setServletUnavailable((UnavailableException)ex );
  +         }
  +         if ( null != getErrorException() ) {
  +             synchronized(this) {
  +                 if ( null!= getErrorException() ) {
  +                     // servlet exception state
  +                     setErrorException( ex );
                    }
                }
            }
  -         throw ex; // will be saved/handled by Handler
        }
  +     // other exceptions will be thrown
       }
   
       protected void doService(HttpServletRequest req, HttpServletResponse res)
  @@ -501,55 +491,46 @@
       // -------------------- Jsp hooks
       ServletWrapper jspServletW=null;
       
  -    // <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 )
  -     jspServletW = (ServletWrapper)context.getServletByName("jsp");
  -     servletClassName = jspServletW.getServletClass();
  -    }
  +//     // <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 )
  +//   jspServletW = (ServletWrapper)context.getServletByName("jsp");
  +//   servletClassName = jspServletW.getServletClass();
  +//     }
   
       // -------------------- Utility methods --------------------
   
  +    /** Set unavailable time
  +     */
       private void setServletUnavailable( UnavailableException ex ) {
  -     // servlet exception state
  -     setErrorException( ex );
  -     if ( ex.isPermanent() ) {
  -         setExceptionPermanent( true );
  -     } else {
  -         setExceptionPermanent( false );
  -         unavailableTime=System.currentTimeMillis();
  -         unavailableTime += ex.getUnavailableSeconds() * 1000;
  -     }
  +     unavailableTime=System.currentTimeMillis();
  +     unavailableTime += ex.getUnavailableSeconds() * 1000;
       }
   
       /** Check if error exception is present and if so, has the error
        expired.  Sets error on request and response if un-expired
        error found.
        */
  -
  -    private void checkErrorExpired( Request req, Response res ) {
  -     // synchronize so another request can't expire the error
  -     synchronized(this) {
  -         // if error still present
  -         if ( isExceptionPresent() ) {
  -             // if permanent exception or timer not expired
  -             if ( isExceptionPermanent() ||
  -                     (unavailableTime - System.currentTimeMillis()) > 0) {
  -                 // save error state on request and response
  -                 saveError( req, res, getErrorException() );
  -             } else {
  -                 // we can try again
  -                 setErrorException(null);
  -                 setExceptionPermanent(false);
  -                 unavailableTime=-1;
  -             }
  -         }
  +    private boolean checkErrorExpired() {
  +     if( unavailableTime == -1 )
  +         return true;
  +     
  +     // if permanent exception this code isn't called
  +     // if timer not expired
  +     if ( (unavailableTime - System.currentTimeMillis()) < 0) {
  +         // we can try again
  +         setErrorException(null);
  +         unavailableTime=-1;
  +         context.log(getServletName() +
  +                     " unavailable time expired, trying again ");
  +         return true;
        }
  +     // still unavailable
  +     return false;
       }
  -
   }
  
  
  
  1.6       +14 -3     
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/WebXmlReader.java
  
  Index: WebXmlReader.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/WebXmlReader.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- WebXmlReader.java 2000/12/08 23:18:29     1.5
  +++ WebXmlReader.java 2000/12/12 00:42:40     1.6
  @@ -53,8 +53,8 @@
        throws TomcatException
       {
        //      addServlet( ctx, "default", 
"org.apache.tomcat.servlets.DefaultServlet");
  -//   addServlet( ctx, "invoker", "org.apache.tomcat.servlets.InvokerServlet");
  -     Handler sw=addServlet( ctx, "jsp", "org.apache.jasper.servlet.JspServlet");
  +     //      addServlet( ctx, "invoker", 
"org.apache.tomcat.servlets.InvokerServlet");
  +     //      Handler sw=addServlet( ctx, "jsp", 
"org.apache.jasper.servlet.JspServlet");
        //      sw.addInitParam("jspCompilerPlugin", 
"org.apache.jasper.compiler.JikesJavaCompiler");
   
   //   ctx.addServletMapping( "/servlet/*", "invoker");
  @@ -187,7 +187,18 @@
            // Servlet
            xh.addRule("web-app/servlet", 
xh.objectCreate("org.apache.tomcat.facade.ServletWrapper") ); // servlet-wrapper
            xh.addRule("web-app/servlet", xh.setParent( "setContext") ); // remove it 
from stack when done
  -         xh.addRule("web-app/servlet", xh.addChild("addServlet", 
"org.apache.tomcat.core.Handler") );
  +         //      xh.addRule("web-app/servlet", xh.addChild("addServlet", 
"org.apache.tomcat.core.Handler") );
  +
  +         xh.addRule("web-app/servlet", new XmlAction() {
  +                        public void end( SaxContext xctx)
  +                            throws Exception {
  +                            ServletWrapper sw=(ServletWrapper)
  +                                xctx.currentObject();
  +                            Context cctx=(Context)xctx.previousObject();
  +                            sw.addServlet(cctx);
  +                        }
  +                    }
  +                );
            // remove it from stack when done
            xh.addRule("web-app/servlet/servlet-name", 
xh.methodSetter("setServletName",0) );
            xh.addRule("web-app/servlet/servlet-class", 
xh.methodSetter("setServletClass",0));
  
  
  
  1.14      +6 -1      
jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/JspInterceptor.java
  
  Index: JspInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/JspInterceptor.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- JspInterceptor.java       2000/12/08 23:18:33     1.13
  +++ JspInterceptor.java       2000/12/12 00:42:42     1.14
  @@ -122,9 +122,14 @@
        }
       }
   
  +    /** Set the HttpJspBase classloader before init,
  +     as required by Jasper
  +    */
       public void preServletInit( Context ctx, Handler sw )
        throws TomcatException
       {
  +     if( ! (sw instanceof ServletWrapper) )
  +         return;
        Servlet theServlet = ((ServletWrapper)sw).getServlet();
        if (theServlet instanceof HttpJspBase)  {
            if( debug > 0 )
  @@ -224,7 +229,7 @@
            // set initial exception on the servlet if one is present
            if ( jspInfo.isExceptionPresent() ) {
                wrapper.setErrorException(jspInfo.getCompileException());
  -             wrapper.setExceptionPermanent(true);
  +             wrapper.setState(Handler.STATE_DISABLED);
            }
        } catch( TomcatException ex ) {
            log("mapJspPage: request=" + req + ", jspInfo=" + jspInfo + ", 
servletName=" + servletName + ", classN=" + classN, ex);
  
  
  
  1.11      +10 -18    
jakarta-tomcat/src/share/org/apache/tomcat/context/ErrorHandler.java
  
  Index: ErrorHandler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/ErrorHandler.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ErrorHandler.java 2000/12/08 23:18:40     1.10
  +++ ErrorHandler.java 2000/12/12 00:42:43     1.11
  @@ -179,16 +179,14 @@
        if( debug>0 )
            ctx.log( "Handler " + errorServlet + " " + errorPath);
   
  -     try {
  -         errorServlet.service( req, res );
  -     } catch( IOException e ) {
  -         // ASSERT: Only thrown by included servlets
  -         // we can ignore it and it's very common - probably the user
  +     errorServlet.service( req, res );
  +     Exception ex=res.getErrorException();
  +     if( ex!=null && ! (ex instanceof IOException) ) {
  +         // we can ignore IOException - probably the user
            // has clicked "STOP"
  -     } catch( Exception e ) {
            // we need to log any other error - something may be
            // broken if the error servlet has errors.
  -         ctx.log( "Error in errorServlet", e);
  +         ctx.log( "Error in errorServlet", ex);
        } 
       }
   
  @@ -280,16 +278,14 @@
        if( debug>0 )
            ctx.log( "Handler " + errorServlet + " " + errorPath);
   
  -     try {
  -         errorServlet.service( req, res );
  -     } catch( IOException e ) {
  -         // ASSERT: Only thrown by included servlets
  -         // we can ignore it and it's very common - probably the user
  +     errorServlet.service( req, res );
  +     Exception ex=res.getErrorException();
  +     if( ! (ex instanceof IOException) ) {
  +         // we can ignore IOException - probably the user
            // has clicked "STOP"
  -     } catch( Exception e ) {
            // we need to log any other error - something may be
            // broken if the error servlet has errors.
  -         ctx.log( "Error in errorServlet", e);
  +         ctx.log( "Error in errorServlet", ex);
        } 
       }
   
  @@ -335,7 +331,6 @@
       int sbNote=0;
       
       NotFoundHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.notFoundHandler";
       }
  @@ -388,7 +383,6 @@
       int sbNote=0;
   
       ExceptionHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.exceptionHandler";
       }
  @@ -462,7 +456,6 @@
       int sbNote=0;
   
       StatusHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.statusHandler";
       }
  @@ -523,7 +516,6 @@
       int sbNote=0;
   
       RedirectHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.redirectHandler";
       }
  
  
  
  1.128     +4 -0      jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java
  
  Index: Context.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java,v
  retrieving revision 1.127
  retrieving revision 1.128
  diff -u -r1.127 -r1.128
  --- Context.java      2000/11/20 21:00:54     1.127
  +++ Context.java      2000/12/12 00:42:44     1.128
  @@ -820,6 +820,7 @@
        throws TomcatException
       {
        wrapper.setContext( this );
  +     wrapper.setState( Handler.STATE_ADDED );
        String name=wrapper.getName();
   
           // check for duplicates
  @@ -835,6 +836,9 @@
       public final  void removeServletByName(String servletName)
        throws TomcatException
       {
  +     Handler h=getServletByName( servletName );
  +     if( h!=null )
  +         h.setState( Handler.STATE_NEW );
        servlets.remove( servletName );
       }
   
  
  
  
  1.26      +168 -75   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.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- Handler.java      2000/12/08 23:18:43     1.25
  +++ Handler.java      2000/12/12 00:42:46     1.26
  @@ -135,15 +135,43 @@
   
       // -------------------- State --------------------
   
  +    /** The handler is new, not part of any application.
  +     *  You must to add the handler to application before doing
  +     *  anything else.
  +     *  To ADDED by calling Context.addHandler().
  +     *  From ADDED by calling Context.removeHandler();
  +     */
       public static final int STATE_NEW=0;
   
  +    /** The handler is added to an application and can be initialized.
  +     *  To READY by calling init(), if success
  +     *  TO DISABLED by calling init if it fails ( exception )
  +     *  From READY by calling destroy()
  +     */
       public static final int STATE_ADDED=1;
  -
  -    public static final int STATE_READY=2;
  -
  -    public static final int STATE_TEMP_DISABLED=3;
   
  +    /** 
  +     * 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()
  +     *  To ADDED by calling destroy()
  +     *  From ADDED by calling init() ( if failure )
  +     */
       public static final int STATE_DISABLED=4;
  +
       
   
       // -------------------- Properties --------------------
  @@ -152,13 +180,8 @@
       
       protected String name;
   
  -    protected int state=STATE_NEW;
  +    private int state=STATE_NEW;
       
  -    /** True if it can handle requests.
  -     404 or error if not.
  -    */
  -    protected boolean initialized=false;
  -    
       Hashtable initArgs=null;
   
       // who creates the servlet definition
  @@ -172,7 +195,6 @@
       protected boolean loadingOnStartup=false;
   
       protected Exception errorException=null;
  -    protected boolean exceptionPermanent=false;
       
       // Debug
       protected int debug=0;
  @@ -278,18 +300,6 @@
        return errorException;
       }
   
  -    public boolean isExceptionPresent() {
  -     return ( errorException != null );
  -    }
  -
  -    public void setExceptionPermanent( boolean permanent ) {
  -     exceptionPermanent = permanent;
  -    }
  -
  -    public boolean isExceptionPermanent() {
  -     return exceptionPermanent;
  -    }
  -
       // -------------------- Jsp specific code
       
       public String getPath() {
  @@ -335,47 +345,115 @@
   
       /** Destroy a handler, and notify all the interested interceptors
        */
  -    public final void destroy() throws Exception {
  -     if ( ! initialized ) {
  +    public final void destroy() {
  +     if ( state!=STATE_READY ) {
  +         // reset exception
            errorException = null;
            return;// already destroyed or not init.
        }
  -     initialized=false;
  +     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 !
  -     doDestroy();
  +     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()
  -     throws Exception
  +    public final void init()
       {
  -     // if initialized, then we were sync blocked when first init() succeeded
  -     if( initialized ) return;
  -     // if exception present, then we were sync blocked when first init() failed
  -     // or an interceptor set an inital exeception
  -     if (errorException != null) throw errorException;
  -     try {
  -         doInit();
  -         initialized=true;
  -     } catch( Exception ex ) {
  -         // save error, assume permanent
  -         setErrorException(ex);
  -         setExceptionPermanent(true);
  +     // 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;
  +         }
        }
       }
   
  -    // XXX XXX XXX
  -    // Must be changed - it's very confusing since it has the same name
  -    // with the servlet's service() method.
  -    // The Handler is at a different ( lower ) level, we should
  -    // use different names ( invoke() ? )
  -
       /** Call the service method, and notify all listeners
        *
        * @exception Exception if an error happens during handling of
  @@ -391,28 +469,16 @@
        *  runtime exceptions )
        */
       public final void service(Request req, Response res)
  -     throws Exception
       {
  -     if( ! initialized ) {
  -         Exception ex=null;
  -         synchronized( this ) {
  -             // we may be initialized when we enter the sync block
  -             if( ! initialized ) {
  -                 try {
  -                     init();
  -                 } catch ( Exception e ) {
  -                     errorException = e;
  -                     exceptionPermanent = true;
  -                 }
  -             }
  -             // get copy of exception, if any, before leaving sync lock
  -             ex=errorException;
  +     if( state!=STATE_READY ) {
  +         if( state!= STATE_DISABLED ) {
  +             init();
            }
  -         // if error occurred
  -         if ( ex != null ) {
  +         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 );
  -             log("Exception in init  " + ex.getMessage(), ex );
                // if in included, defer handling to higher level
                if (res.isIncluded()) return;
                // handle init error since at top level
  @@ -421,43 +487,51 @@
                else
                    contextM.handleError( req, res, ex );
                return;
  -         }
  +         } 
        }
        
  -     //      if( ! internal ) {
  -     // no distinction for internal handlers !
        BaseInterceptor reqI[]=
            req.getContainer().getInterceptors(Container.H_preService);
        for( int i=0; i< reqI.length; i++ ) {
            reqI[i].preService( req, res );
        }
  -     //}
   
  +     Exception serviceException=null;
        try {
            doService( req, res );
        } catch( Exception ex ) {
            // save error state on request and response
  -         saveError( req, res, ex );
  +         serviceException=ex;
  +         saveError( req, res, ex);
        }
   
  -     // continue with the postService
  -     //      if( ! internal ) {
  +     // continue with the postService ( roll back transactions, etc )
        reqI=req.getContainer().getInterceptors(Container.H_postService);
        for( int i=0; i< reqI.length; i++ ) {
            reqI[i].postService( req, res );
        }
  -     //      }
   
        // if no error
  -     if( ! res.isExceptionPresent() ) return;
  +     if( serviceException == null ) return;
  +
        // if in included, defer handling to higher level
        if (res.isIncluded()) return;
  +     
        // handle original error since at top level
        contextM.handleError( req, res, res.getErrorException() );
       }
   
       // -------------------- methods you can override --------------------
   
  +    protected void handleInitError( Throwable t ) {
  +
  +    }
  +    
  +    protected void handleServiceError( Request req, Response res, Throwable t )
  +    {
  +
  +    }
  +    
       /** Reload notification. This hook is called whenever the
        *  application ( this handler ) is reloaded
        */
  @@ -471,6 +545,22 @@
   
       }
   
  +    /** 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.
        */
  @@ -505,7 +595,10 @@
   
       protected final void log( String s ) {
        if ( logger==null ) 
  -         contextM.log(s);
  +         if( contextM!=null )
  +             contextM.log(s);
  +         else
  +             System.out.println("(cm==null) " + s );
        else 
            logger.log(s);
       }
  
  
  
  1.26      +4 -5      
jakarta-tomcat/src/share/org/apache/tomcat/request/AccessInterceptor.java
  
  Index: AccessInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/AccessInterceptor.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- AccessInterceptor.java    2000/12/08 23:18:48     1.25
  +++ AccessInterceptor.java    2000/12/12 00:42:48     1.26
  @@ -216,8 +216,10 @@
        Container ctxCt=ctx.getContainer();
        SecurityConstraints ctxSecurityC=(SecurityConstraints)ctxCt.
            getNote( secMapNote );
  -     if( ctxSecurityC==null)
  -         ctxCt.setNote( secMapNote, new SecurityConstraints() );
  +     if( ctxSecurityC==null) {
  +         ctxSecurityC= new SecurityConstraints();
  +         ctxCt.setNote( secMapNote, ctxSecurityC );
  +     }
   
        if( ct.getRoles()!=null || ct.getTransport()!=null ) {
            if( debug > 0 )
  @@ -342,7 +344,6 @@
       int sbNote=0;
       
       BasicAuthHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.basicAuthHandler";
       }
  @@ -389,7 +390,6 @@
   class FormAuthHandler extends Handler {
       
       FormAuthHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.formAuthHandler";
       }
  @@ -447,7 +447,6 @@
   class FormSecurityCheckHandler extends Handler {
       
       FormSecurityCheckHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.formSecurityCheck";
       }
  
  
  
  1.26      +0 -2      
jakarta-tomcat/src/share/org/apache/tomcat/request/StaticInterceptor.java
  
  Index: StaticInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/StaticInterceptor.java,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- StaticInterceptor.java    2000/12/08 23:18:49     1.25
  +++ StaticInterceptor.java    2000/12/12 00:42:48     1.26
  @@ -217,7 +217,6 @@
       int realFileNote;
   
       FileHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.fileHandler";
       }
  @@ -329,7 +328,6 @@
       int sbNote=0;
       
       DirHandler() {
  -     initialized=true;
        setOrigin( Handler.ORIGIN_INTERNAL );
        name="tomcat.dirHandler";
       }
  
  
  
  1.15      +1 -1      jakarta-tomcat/src/share/org/apache/tomcat/startup/Main.java
  
  Index: Main.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/startup/Main.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- Main.java 2000/11/30 06:17:13     1.14
  +++ Main.java 2000/12/12 00:42:49     1.15
  @@ -282,7 +282,7 @@
                                      "org.apache.tomcat.task.StartTomcat");
            processArgs( proxy, args );
            setAttribute( proxy, "parentClassLoader", parentL );
  -         setAttribute( proxy, "serverClassPath", urls );
  +         //      setAttribute( proxy, "serverClassPath", urls );
            execute(  proxy, "execute" );
            return;
        } catch( Exception ex ) {
  
  
  

Reply via email to