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.
*