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/02/17 08:52:25 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/servlets JSecurityCheck.java AuthServlet.java DefaultErrorPage.java

costin      00/02/16 23:52:24

  Modified:    src/examples/WEB-INF web.xml
               src/share/org/apache/tomcat/context DefaultCMSetter.java
                        LoadOnStartupInterceptor.java
               src/share/org/apache/tomcat/core ContextManager.java
                        HttpServletResponseFacade.java Request.java
                        RequestDispatcherImpl.java RequestImpl.java
                        ServletWrapper.java
               src/share/org/apache/tomcat/request SecurityCheck.java
               src/share/org/apache/tomcat/service
                        Ajp11ConnectionHandler.java
               src/share/org/apache/tomcat/service/connector
                        Ajp12ConnectionHandler.java
                        Ajp23ConnectionHandler.java
                        JNIConnectionHandler.java
               src/share/org/apache/tomcat/service/http
                        HttpConnectionHandler.java
               src/share/org/apache/tomcat/servlets AuthServlet.java
                        DefaultErrorPage.java
  Added:       src/examples/jsp/security login.jsp
               src/examples/jsp/security/protected index.jsp
               src/share/org/apache/tomcat/servlets JSecurityCheck.java
  Log:
  Ok, I hope this is the last "big" change for 3.1
  
  Error handling was broken ( i.e. error-page was not called for error codes,
  exceptions were handled at-hoc).
  
  Added a single method that handles that, in ContextManager, added code to
  redirect to error pages for special HTTP errors, try hard to avoid loops.
  
  We have a bit too much debugging on, but that's not a but and will be removed
  before 3.1 ( since we are bug-fixing we should keep it until everything
  works )
  
  Implemented form login, added an example. Now we should have BASIC and FORM
  working ( except that no auth repository is plugged in, any user/password will
  be accepted ). I'll add users.xml before 3.1 ( as a bug-fix, not a feature :-)
  
  Revision  Changes    Path
  1.3       +34 -0     jakarta-tomcat/src/examples/WEB-INF/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/examples/WEB-INF/web.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- web.xml	1999/10/20 22:07:58	1.2
  +++ web.xml	2000/02/17 07:52:16	1.3
  @@ -64,4 +64,38 @@
              /WEB-INF/jsp/example-taglib.tld
           </taglib-location>
       </taglib>
  +
  +    <login-config>
  +      <auth-method>FORM</auth-method>
  +      <realm-name>examples</realm-name>
  +      <form-login-config><form-login-page>/jsp/security/login.jsp</form-login-page>
  +      </form-login-config>
  +    </login-config>
  +
  +    <security-constraint>
  +      <web-resource-collection>
  +         <web-resource-name>a</web-resource-name>
  +         <url-pattern>/jsp/security/protected/*</url-pattern>
  +         <url-pattern>/jsp/security/protected1/</url-pattern>
  +         <http-method>GET</http-method>
  +         <http-method>POST</http-method>
  +      </web-resource-collection>
  +
  +      <web-resource-collection>
  +         <web-resource-name>a</web-resource-name>
  +         <url-pattern>/foo2/*</url-pattern>
  +         <url-pattern>/bar2/*</url-pattern>
  +      </web-resource-collection>
  +
  +      <auth-constraint>
  +         <role-name>tomcat</role-name>
  +         <role-name>role1</role-name>
  +      </auth-constraint>
  +
  +      <!-- No https support, later
  +          user-data-constraint>
  +         <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  +      </user-data-constraint -->
  +    </security-constraint>
  +
   </web-app>
  
  
  
  1.1                  jakarta-tomcat/src/examples/jsp/security/login.jsp
  
  Index: login.jsp
  ===================================================================
  <html>
  <body>
  <h1>Login page for examples</h1>
  
  <form method="POST" action="j_security_check" >
   <input type="text" name="j_username"> 
   <input type="password" name="j_password"> 
   
   <input type="submit" name="j_security_check">
  </form>
  
  </body>
  </html>
  
  
  
  1.1                  jakarta-tomcat/src/examples/jsp/security/protected/index.jsp
  
  Index: index.jsp
  ===================================================================
  <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
  <html>
  <body>
  <h1>Great, you logged in </h1>
  </body>
  </html>
  
  
  
  1.16      +8 -2      jakarta-tomcat/src/share/org/apache/tomcat/context/DefaultCMSetter.java
  
  Index: DefaultCMSetter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/DefaultCMSetter.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- DefaultCMSetter.java	2000/02/16 00:48:44	1.15
  +++ DefaultCMSetter.java	2000/02/17 07:52:18	1.16
  @@ -107,13 +107,19 @@
   	// Set default session manager if none set
   	if( ctx.getSessionManager() == null ) 
   	    ctx.setSessionManager(new org.apache.tomcat.session.StandardSessionManager());
  -
   	//  Alternative: org.apache.tomcat.session.ServerSessionManager.getManager();
  +
   	ServletWrapper authWrapper=new ServletWrapper();
   	authWrapper.setContext( ctx );
   	authWrapper.setServletClass( "org.apache.tomcat.servlets.AuthServlet" );
  -	authWrapper.setServletName( "authServlet");
  +	authWrapper.setServletName( "tomcat.authServlet");
   	ctx.addServlet( authWrapper );
  +
  +	ServletWrapper errorWrapper=new ServletWrapper();
  +	errorWrapper.setContext( ctx );
  +	errorWrapper.setServletClass( "org.apache.tomcat.servlets.DefaultErrorPage" );
  +	errorWrapper.setServletName( "tomcat.errorPage");
  +	ctx.addServlet( errorWrapper );
   
   	// XXX Loader properties - need to be set on loader!!
   	//ctx.setServletLoader( new org.apache.tomcat.loader.ServletClassLoaderImpl());
  
  
  
  1.9       +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.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- LoadOnStartupInterceptor.java	2000/02/14 04:59:38	1.8
  +++ LoadOnStartupInterceptor.java	2000/02/17 07:52:18	1.9
  @@ -159,6 +159,7 @@
   	String path=result.getPath();
   	RequestImpl request = new RequestImpl();
   	ResponseImpl response = new ResponseImpl();
  +	request.setContextManager( context.getContextManager());
   	request.recycle();
   	response.recycle();
   	
  
  
  
  1.47      +122 -48   jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java
  
  Index: ContextManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- ContextManager.java	2000/02/16 17:13:22	1.46
  +++ ContextManager.java	2000/02/17 07:52:19	1.47
  @@ -66,6 +66,8 @@
   import org.apache.tomcat.request.*;
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.logging.*;
  +import javax.servlet.*;
  +import javax.servlet.http.*;
   import java.io.*;
   import java.net.*;
   import java.util.*;
  @@ -479,71 +481,43 @@
       */
       public void service( Request rrequest, Response rresponse ) {
   	try {
  +	    rrequest.setContextManager( this );
   	    rrequest.setResponse(rresponse);
   	    rresponse.setRequest(rrequest);
   
  -	    // XXX
  -	    //    return if an error was detected in processing the
  -	    //    request line
  -	    if (rresponse.getStatus() >= 400) {
  -		rresponse.finish();
  -		rrequest.recycle();
  -		rresponse.recycle();
  -		return;
  -	    }
  -
  -	    // XXX Hardcoded - it will be changed in the next step.( costin )
  -	    processRequest( rrequest );
  +	    // wront request - parsing error
  +	    int status=rresponse.getStatus();
   
  -	    authenticate( rrequest, rresponse );
  -
  -	    int err=authorize( rrequest, rresponse );
  -	    if( err != 0 ) {
  -		// redirect to the right servlet 
  -		Context ctx=rrequest.getContext();
  -		String authMethod=ctx.getAuthMethod();
  -		ServletWrapper authWrapper=ctx.getServletByName( "authServlet" );
  -		rrequest.setWrapper( authWrapper );
  -		
  -		// unauthorized access, redirect to login page.
  -		// XXX authorize will set request
  -	    }
  -	    
  +	    if( status < 400 )
  +		status= processRequest( rrequest );
   	    
  -	    if( rrequest.getWrapper() == null ) {
  -		log("ERROR: mapper returned no wrapper ");
  -		log(rrequest.toString() );
  -		// XXX send an error - it shouldn't happen, mapper is broken
  +	    if(status==0)
  +		status=authenticate( rrequest, rresponse );
  +	    if(status == 0)
  +		status=authorize( rrequest, rresponse );
  +	    if( status == 0 ) {
  +		rrequest.getWrapper().handleRequest(rrequest,
  +						    rresponse);
   	    } else {
  -		// do it
  -		rrequest.getWrapper().handleRequest(rrequest.getFacade(),
  -						    rresponse.getFacade());
  +		// something went wrong
  +		handleError( rrequest, rresponse, null, status );
   	    }
   	    
  -	    // finish and clean up
   	    rresponse.finish();
  -	    
  -	} catch (Exception e) {
  -	    if(e instanceof IOException && "Broken pipe".equals(e.getMessage()) ) {
  -		log("Broken pipe " + rrequest.getRequestURI());
  -		return;
  -	    }
  -	    // XXX
  -	    // this isn't what we want, we want to log the problem somehow
  -	    log("HANDLER THREAD PROBLEM: " + e);
  -	    log("Request: " + rrequest);
  -	    e.printStackTrace();
  +	    rrequest.recycle();
  +	    rresponse.recycle();
  +	} catch (Throwable t) {
  +	    handleError( rrequest, rresponse, t, 0 );
   	}
  +	return;
       }
   
  -    // XXX need to be changed to use a full sub-request model (costin)
  -    
       /** Will find the ServletWrapper for a servlet, assuming we already have
        *  the Context. This is used by Dispatcher and getResource - where the Context
        *  is already known.
        */
       int processRequest( Request req ) {
  -
  +	req.setContextManager( this );
   	log("ProcessRequest: "+req.toString(), Logger.DEBUG);
   
   	for( int i=0; i< requestInterceptors.size(); i++ ) {
  @@ -580,6 +554,106 @@
   	    ((RequestInterceptor)requestInterceptors.elementAt(i)).beforeBody( req, res );
   	}
   	return 0;
  +    }
  +
  +    void handleError( Request req, Response res , Throwable t, int code ) {
  +	Context ctx = req.getContext();
  +	if(ctx==null) {
  +	    ///*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
  +	    ctx=getContext("");
  +	}
  +
  +	if( code!=0) 
  +	    ctx.log("Status: " + code + " in " + req );
  +	if( t!=null) 
  +	    ctx.log("Exception: " + t.getMessage() + " in " + req );
  +	
  +	String path=null;
  +	ServletWrapper errorServlet=null;
  +
  +	// normal redirects or non-errors
  +	if( code!=0 && code < 400 ) {
  +	    errorServlet=ctx.getServletByName("tomcat.errorPage");
  +	} else if( req.getAttribute("javax.servlet.error.status_code") != null ||
  +	    req.getAttribute("javax.servlet.error.exception_type")!=null) {
  +	    
  +	    if( ctx.getDebug() > 0 ) ctx.log( "Error: exception inside exception servlet " +
  +					      req.getAttribute("javax.servlet.error.status_code") + " " +
  +					      req.getAttribute("javax.servlet.error.exception_type"));
  +	    errorServlet=ctx.getServletByName("tomcat.errorPage");
  +	}
  +
  +	if( t==null) {
  +	    if( code==0 )
  +		code=res.getStatus();
  +	    // we can't support error pages for non-errors, it's to
  +	    // complex and insane
  +	    if( code >= 400 )
  +		path = ctx.getErrorPage( code );
  +	    
  +	    if( code==HttpServletResponse.SC_UNAUTHORIZED ) {
  +		// set extra info for login page
  +		if( errorServlet==null)
  +		    errorServlet=ctx.getServletByName("tomcat.authServlet");
  +		if( ctx.getDebug() > 0 ) ctx.log( "Setting auth servlet " + errorServlet );
  +	    }
  +            req.setAttribute("javax.servlet.error.status_code",new Integer( code));
  +	} else {
  +	    // Scan the exception's inheritance tree looking for a rule
  +	    // that this type of exception should be forwarded
  +	    Class clazz = t.getClass();
  +	    while (path == null && clazz != null) {
  +		String name = clazz.getName();
  +		path = ctx.getErrorPage(name);
  +		clazz = clazz.getSuperclass();
  +	    }
  +	    req.setAttribute("javax.servlet.error.exception_type", t.getClass());
  +            req.setAttribute("javax.servlet.error.message", t.getMessage());
  +	    req.setAttribute("tomcat.servlet.error.throwable", t);
  +	}
  +
  +	// Save the original request, we want to report it
  +	// and we need to use it in the "authentication" case to implement
  +	// the strange requirements for login pages
  +	req.setAttribute("tomcat.servlet.error.request", req);
  +
  +
  +	// No error page or "Exception in exception handler", call internal servlet
  +	if( path==null && errorServlet==null)
  +	    errorServlet=ctx.getServletByName("tomcat.errorPage");
  +
  +	// Try a normal "error page"
  +	if( errorServlet==null && path != null ) {
  +	    try {
  +		RequestDispatcher rd = ctx.getRequestDispatcher(path);
  +		
  +		// try a forward
  +		res.reset();
  +		if (res.isStarted()) 
  +		    rd.include(req.getFacade(), res.getFacade());
  +		else
  +		    rd.forward(req.getFacade(), res.getFacade());
  +		return ;
  +	    } catch( Throwable t1 ) {
  +		// nothing - we'll call DefaultErrorPage
  +	    }
  +	}
  +	
  +	// If No handler or an error happened in handler 
  +	// Default handler
  +	// loop control
  +	if( req.getAttribute("tomcat.servlet.error.handler") != null &&
  +	    code >= 400 ) {
  +	    // error page for 404 doesn't exist... ( or watchdog tests :-)
  +	    ctx.log( "Error/loop in default error handler " + req );
  +	    ctx.log( "Error/loop " + code + " " + t + " " +  path );
  +	} else {
  +	    if( ctx.getDebug() > 0 ) ctx.log( "Error: Calling servlet " + errorServlet );
  +	    req.setAttribute("tomcat.servlet.error.handler", errorServlet);
  +	    errorServlet.handleRequest(req.getFacade(),res.getFacade());
  +	    // will call this if any error happens
  +	}
  +	return;
       }
       
       // -------------------- Sub-Request mechanism --------------------
  
  
  
  1.4       +5 -14     jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java
  
  Index: HttpServletResponseFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- HttpServletResponseFacade.java	2000/02/01 21:39:38	1.3
  +++ HttpServletResponseFacade.java	2000/02/17 07:52:19	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v 1.3 2000/02/01 21:39:38 costin Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/02/01 21:39:38 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v 1.4 2000/02/17 07:52:19 costin Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/02/17 07:52:19 $
    *
    * ====================================================================
    *
  @@ -157,18 +157,9 @@
       public void sendError(int sc, String msg) throws IOException {
   	setStatus( sc );
   	Request request=response.getRequest();
  -	request.setAttribute("javax.servlet.error.status_code",
  -			     String.valueOf(sc));
   	request.setAttribute("javax.servlet.error.message", msg);
  -
  -	// XXX need to customize it
  -	Servlet errorP=new org.apache.tomcat.servlets.DefaultErrorPage();
  -	try {
  -	    errorP.service(request.getFacade(),this);
  -	} catch (ServletException ex ) {
  -	    // shouldn't happen!
  -	    ex.printStackTrace();
  -	}
  +	ContextManager cm=request.getContextManager();
  +	cm.handleError( request, response, null, sc );
       }
   
       public void sendRedirect(String location)
  
  
  
  1.29      +6 -0      jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java
  
  Index: Request.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- Request.java	2000/02/16 17:56:11	1.28
  +++ Request.java	2000/02/17 07:52:19	1.29
  @@ -241,6 +241,12 @@
        */
       public HttpServletRequestFacade getFacade() ;
   
  +    /** Pointer to the server engine - for errors, etc
  +     */
  +    public void setContextManager( ContextManager cm );
  +
  +    public ContextManager getContextManager();
  +    
       // -------------------- Internal/deprecated--------------------
       // Derived from parsing query string and body (for POST)
   
  
  
  
  1.18      +3 -3      jakarta-tomcat/src/share/org/apache/tomcat/core/RequestDispatcherImpl.java
  
  Index: RequestDispatcherImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestDispatcherImpl.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- RequestDispatcherImpl.java	2000/02/16 17:13:22	1.17
  +++ RequestDispatcherImpl.java	2000/02/17 07:52:19	1.18
  @@ -157,8 +157,8 @@
   
   	// CM should have set the wrapper - call it
   	// LOG	System.out.println("Forward " + realRequest.getServletPath());
  -	realRequest.getWrapper().handleRequest((HttpServletRequestFacade)request,
  -						   (HttpServletResponseFacade)response);
  +	realRequest.getWrapper().handleRequest(realRequest,
  +						realResponse);
       }
   
       public void include(ServletRequest request, ServletResponse response)
  @@ -253,7 +253,7 @@
    	// now it's really strange: we call the wrapper on the subrequest
   	// for the realRequest ( since the real request will still have the
   	// original handler/wrapper )
  -	subRequest.getWrapper().handleRequest(realRequest.getFacade() , (HttpServletResponseFacade)response);
  +	subRequest.getWrapper().handleRequest(realRequest , realResponse);
   
   	// After request, we want to restore the include attributes - for
   	// chained includes.
  
  
  
  1.19      +12 -3     jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java
  
  Index: RequestImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- RequestImpl.java	2000/02/16 00:30:29	1.18
  +++ RequestImpl.java	2000/02/17 07:52:19	1.19
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.18 2000/02/16 00:30:29 costin Exp $
  - * $Revision: 1.18 $
  - * $Date: 2000/02/16 00:30:29 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.19 2000/02/17 07:52:19 costin Exp $
  + * $Revision: 1.19 $
  + * $Date: 2000/02/17 07:52:19 $
    *
    * ====================================================================
    *
  @@ -108,6 +108,7 @@
       protected Response response;
       protected HttpServletRequestFacade requestFacade;
       protected Context context;
  +    protected ContextManager contextM;
       protected Hashtable attributes = new Hashtable();
   
       protected boolean didReadFormData;
  @@ -342,6 +343,14 @@
       
       public void setContext(Context context) {
   	this.context = context;
  +    }
  +
  +    public void setContextManager( ContextManager cm ) {
  +	contextM=cm;
  +    }
  +
  +    public ContextManager getContextManager() {
  +	return contextM;
       }
   
       public Cookie[] getCookies() {
  
  
  
  1.29      +131 -262  jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java
  
  Index: ServletWrapper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- ServletWrapper.java	2000/02/16 17:13:23	1.28
  +++ ServletWrapper.java	2000/02/17 07:52:20	1.29
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java,v 1.28 2000/02/16 17:13:23 costin Exp $
  - * $Revision: 1.28 $
  - * $Date: 2000/02/16 17:13:23 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ServletWrapper.java,v 1.29 2000/02/17 07:52:20 costin Exp $
  + * $Revision: 1.29 $
  + * $Date: 2000/02/17 07:52:20 $
    *
    * ====================================================================
    *
  @@ -82,6 +82,7 @@
       protected StringManager sm = StringManager.getManager("org.apache.tomcat.core");
   
       protected Context context;
  +    protected ContextManager contextM;
   
       // servletName is stored in config!
       protected String servletClassName; // required
  @@ -95,6 +96,7 @@
       // optional informations
       protected String description = null;
   
  +    boolean initialized=false;
       // Usefull info for class reloading
       protected boolean isReloadable = false;
       // information + make sure destroy is called when no other servlet
  @@ -118,6 +120,7 @@
   
       public void setContext( Context context) {
           this.context = context;
  +	contextM=context.getContextManager();
   	config.setContext( context );
   	isReloadable=context.getReloadable();
       }
  @@ -206,16 +209,45 @@
       }
       
       void destroy() {
  +	initialized=false;
   	if (servlet != null) {
   	    synchronized (this) {
  -		waitForDestroy();
  +		// 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 )
  +		while (serviceCount > 0) {
  +		    try {
  +			wait(30000);
  +			
  +			break;
  +		    } catch (InterruptedException e) { }
  +		}
  +
   		try {
  -		    handleDestroy( context, servlet );
  -		} catch(IOException ioe) {
  -		    ioe.printStackTrace();
  -		    // Should never come here...
  -		} catch(ServletException se) {
  -		    se.printStackTrace();
  +		    ContextInterceptor cI[]=context.getContextInterceptors();
  +		    for( int i=0; i<cI.length; i++ ) {
  +			try {
  +			    cI[i].preServletDestroy( context, this ); // ignore the error - like in the original code
  +			} catch( TomcatException ex) {
  +			    ex.printStackTrace();
  +			}
  +			
  +		    }
  +		    servlet.destroy();
  +		    for( int i=cI.length-1; i>=0; i-- ) {
  +			try {
  +			    cI[i].postServletDestroy( context, this ); // ignore the error - like in the original code
  +			} catch( TomcatException ex) {
  +			    ex.printStackTrace();
  +			}
  +			
  +		    }
  +		} catch(Exception ex) {
  +		    ex.printStackTrace();
   		    // Should never come here...
   		}
   	    }
  @@ -236,58 +268,52 @@
   	}
   	
   	servlet = (Servlet)servletClass.newInstance();
  -
  +	
   	config.setServletClassName(servlet.getClass().getName());
  +	initServlet();
  +    }
   
  +    
  +    void initServlet()
  +	throws ClassNotFoundException, InstantiationException,
  +	IllegalAccessException, ServletException
  +    {
   	try {
   	    final Servlet sinstance = servlet;
   	    final ServletConfigImpl servletConfig = config;
   	    
  -	    handleInit(context, servlet, servletConfig);
  -	} catch(IOException ioe) {
  -	    ioe.printStackTrace();
  -	    // Should never come here...
  -	}
  -    }
  -
  -    // XXX XXX need to go directly to Jsp API 
  -    void handleJspRequest(final HttpServletRequestFacade request,
  -			      final HttpServletResponseFacade response)
  -	throws IOException
  -    {
  -	// "Special" JSP
  -	String requestURI = path + request.getPathInfo();
  -	RequestDispatcher rd = request.getRequestDispatcher(requestURI);
  -	
  -	try {
  -	    if (! response.getRealResponse().isStarted())
  -		rd.forward(request, response);
  -	    else
  -		rd.include(request, response);
  +	    ContextInterceptor cI[]=context.getContextInterceptors();
  +	    for( int i=0; i<cI.length; i++ ) {
  +		try {
  +		    cI[i].preServletInit( context, this ); // ignore the error - like in the original code
  +		} catch( TomcatException ex) {
  +		    ex.printStackTrace();
  +		}
  +	    }
  +	    servlet.init(servletConfig);
  +	    // if an exception is thrown in init, no end interceptors will be called.
  +	    // that was in the origianl code
  +	    
  +	    for( int i=cI.length-1; i>=0; i-- ) {
  +		try {
  +		    cI[i].postServletInit( context, this ); // ignore the error - like in the original code
  +		} catch( TomcatException ex) {
  +		    ex.printStackTrace();
  +		}
   		
  -	} catch (ServletException se) {
  -	    se.printStackTrace();
  -	    response.sendError(404);
  -	} catch (IOException ioe) {
  +	    }
  +	    initialized=true;
  +	} catch(Exception ioe) {
   	    ioe.printStackTrace();
  -	    response.sendError(404);
  +	    // Should never come here...
   	}
  -	return;
       }
  -    
  -    public void handleRequest(final HttpServletRequestFacade request,
  -			      final HttpServletResponseFacade response)
  -	throws IOException
  -    {
  -	if( path != null ) handleJspRequest( request, response );
   
  -	Context context = getContext();
  -
  -	// Reloading
  -	// XXX ugly - should find a better way to deal with invoker
  -	// The problem is that we are just clearing up invoker, not
  -	// the class loaded by invoker.
  -
  +    // Reloading
  +    // XXX ugly - should find a better way to deal with invoker
  +    // The problem is that we are just clearing up invoker, not
  +    // the class loaded by invoker.
  +    void handleReload() {
   	// That will be reolved after we reset the context - and many
   	// other conflicts.
   	if( isReloadable && ! "invoker".equals( getServletName())) {
  @@ -295,6 +321,7 @@
   	    if( loader!=null) {
   		// XXX no need to check after we remove the old loader
   		if( loader.shouldReload() ) {
  +		    initialized=false;
   		    loader.reload();
   		    servlet=null;
   		    servletClass=null;
  @@ -312,232 +339,74 @@
   		}
   	    }
   	}
  -	
  -	
  -	if (servlet == null) {
  -	    synchronized (this) {
  -		try {
  -		    loadServlet();
  -		} catch (ClassNotFoundException e) {
  -		    response.sendError(404, "Class not found " + servletClassName);
  -		    return;
  -		} catch (Exception e) {
  -		    // Make sure the servlet will never
  -		    // service a request
  -		    servlet = null;
  -		    sendInternalServletError(e, request, response);
  -		    return;
  -		}
  -	    }
  -	}
  -
  -        try {
  -	    synchronized(this) {
  -		// logic for un-loading
  -		serviceCount++;
  -	    }
  -
  -	    
  -	    handleInvocation( context, servlet, request, response );
  -
  -	} catch (ServletException e) {
  -	    // XXX
  -	    // if it's an unvailable exception, we probably want
  -	    // to paint a different screen
  -            handleException(request, response, e);
  -        } catch (SocketException e) {
  -	    // replace with Log:
  -	    System.out.println("Socket Exception : " + e.getMessage());
  -        } catch (Throwable e) {
  -	    // XXX
  -	    // decide which exceptions we should not eat at this point
  -            handleException(request, response, e);
  -	} finally {
  -	    synchronized(this) {
  -		serviceCount--;
  -		notifyAll();
  -	    }
  -	}
       }
  -
  -    public void handleException(HttpServletRequestFacade request,
  -				HttpServletResponseFacade response,
  -				Throwable t)
  -    {
  -        Context context = request.getRealRequest().getContext();
  -        ServletContextFacade contextFacade = context.getFacade();
  -
  -        // Scan the exception's inheritance tree looking for a rule
  -        // that this type of exception should be forwarded
  -
  -        String path = null;
  -        Class clazz = t.getClass();
  -
  -        while (path == null && clazz != null) {
  -            String name = clazz.getName();
  -            path = context.getErrorPage(name);
  -            clazz = clazz.getSuperclass();
  -        }
  -	
  -        // If path is non-null, we should do a forward
  -        // Don't do a forward if exception_type is already defined though to
  -        // avoid an infinite loop.
  -
  -        if (path != null &&
  -	    request.getAttribute(
  -                Constants.ATTRIBUTE_ERROR_EXCEPTION_TYPE) == null) {
  -            RequestDispatcher rd = contextFacade.getRequestDispatcher(path);
  -
  -            // XXX 
  -            // The spec should really be changed to allow us to include
  -            // the full exception object.  Oh well.
  -
  -            request.setAttribute(Constants.ATTRIBUTE_ERROR_EXCEPTION_TYPE,
  -				 t.getClass().getName());
  -            request.setAttribute(Constants.ATTRIBUTE_ERROR_MESSAGE,
  -				 t.getMessage());
  -
  -            try {
  -		// A forward would be ideal, so reset and try it
  -
  -		response.getRealResponse().reset();
  -
  -		if (response.getRealResponse().isStarted()) 
  -		    rd.include(request, response);
  -		else
  -		    rd.forward(request, response);
  -            } catch (IOException e) {
  -		e.printStackTrace();
  -                // Shouldn't get here
  -            } catch (ServletException e) {
  -		e.printStackTrace();
  -                // Shouldn't get here
  -            }
  -        } else {
  -            try {
  -		sendInternalServletError( t, request, response);
  -	    } catch (IOException e) {
  -                e.printStackTrace();
  -		// ???
  -            }
  -        }
  -    }
  -
  -    void sendInternalServletError( Throwable t, HttpServletRequestFacade request,
  -				   HttpServletResponseFacade response )
  -	throws IOException
  -    {
  -	// Used to communicate with Default Error Page
  -		request.setAttribute("tomcat.error.throwable", t);
  -		// XXX need to make this configurable, any servlet
  -		// can act as the default error handler
  -
  -		// Need to do a normal servlet invocation!
  -		try {
  -		    Servlet errorP=new org.apache.tomcat.servlets.DefaultErrorPage();
  -		    errorP.service(request,response);
  -		} catch(Exception ex) {
  -		    System.out.println("FATAL: error in error handler");
  -		    ex.printStackTrace();
  -		}
  -    }
       
  -    /** Call the init method and all init interceptors
  -     */
  -    protected void handleInit(Context context, Servlet servlet, ServletConfig servletConfig )
  -	throws ServletException, IOException
  +    public void handleRequest(Request req, Response res)
       {
  -	ContextInterceptor cI[]=context.getContextInterceptors();
  -	for( int i=0; i<cI.length; i++ ) {
  -	    try {
  -		cI[i].preServletInit( context, this ); // ignore the error - like in the original code
  -	    } catch( TomcatException ex) {
  -		ex.printStackTrace();
  +	try {
  +	    if( path != null ) {
  +		// XXX call JspServlet directly, did anyone tested it ??
  +		String requestURI = path + req.getPathInfo();
  +		RequestDispatcher rd = req.getContext().getRequestDispatcher(requestURI);
  +		
  +		if (! res.isStarted())
  +		    rd.forward(req.getFacade(), res.getFacade());
  +		else
  +		    rd.include(req.getFacade(), res.getFacade());
  +		return;
   	    }
  -	}
  -	servlet.init(servletConfig);
  -	// if an exception is thrown in init, no end interceptors will be called.
  -	// that was in the origianl code
  +	    
  +	    handleReload();
   
  -	for( int i=cI.length-1; i>=0; i-- ) {
  -	    try {
  -		cI[i].postServletInit( context, this ); // ignore the error - like in the original code
  -	    } catch( TomcatException ex) {
  -		ex.printStackTrace();
  +	    if( ! initialized )
  +		loadServlet();
  +	    
  +	    // XXX to expensive  per/request, un-load is not so frequent and
  +	    // the API doesn't require a special state for destroy
  +	    // synchronized(this) {
  +	    // 		// logic for un-loading
  +	    // 		serviceCount++;
  +	    //
  +	    
  +	    RequestInterceptor cI[]=context.getRequestInterceptors();
  +	    for( int i=0; i<cI.length; i++ ) {
  +		cI[i].preService( req, res ); // ignore the error - like in the original code
   	    }
  -
  -	}
  -    }
  -
  -    /** Call destroy(), with all interceptors before and after in the
  -	right order;
  -    */
  -    protected void handleDestroy(Context context, Servlet servlet )
  -	throws ServletException, IOException
  -    {
  -	ContextInterceptor cI[]=context.getContextInterceptors();
  -	for( int i=0; i<cI.length; i++ ) {
  -	    try {
  -		cI[i].preServletDestroy( context, this ); // ignore the error - like in the original code
  -	    } catch( TomcatException ex) {
  -		ex.printStackTrace();
  +	    
  +	    if (servlet instanceof SingleThreadModel) {
  +		synchronized(servlet) {
  +		    servlet.service(req.getFacade(), res.getFacade());
  +		}
  +	    } else {
  +		servlet.service(req.getFacade(), res.getFacade());
   	    }
  -
  -	}
  -	servlet.destroy();
  -	for( int i=cI.length-1; i>=0; i-- ) {
  -	    try {
  -		cI[i].postServletDestroy( context, this ); // ignore the error - like in the original code
  -	    } catch( TomcatException ex) {
  -		ex.printStackTrace();
  +	    
  +	    for( int i=cI.length-1; i>=0; i-- ) {
  +		cI[i].postService( req , res ); // ignore the error - like in the original code
   	    }
  -
  +	    // 	} finally {
  +	    // 	    synchronized(this) {
  +	    // 		serviceCount--;
  +	    // 		notifyAll();
  +	    // 	    }
  +	    // 	}
  +	} catch( Throwable t ) {
  +	    contextM.handleError( req, res, t, 0 );
   	}
       }
  -    
   
  -    /** Call service(), with all interceptors before and after in the
  -	right order;
  -    */
  -    protected void handleInvocation(Context ctx, Servlet servlet,
  -				  HttpServletRequestFacade request, HttpServletResponseFacade response )
  -	throws ServletException, IOException
  +    /** @deprecated
  +     */
  +    public void handleRequest(final HttpServletRequestFacade request,
  +			      final HttpServletResponseFacade response)
       {
  -	RequestInterceptor cI[]=context.getRequestInterceptors();
  -	for( int i=0; i<cI.length; i++ ) {
  -	    cI[i].preService( request.getRealRequest(), response.getRealResponse() ); // ignore the error - like in the original code
  -	}
  -	
  -	if (servlet instanceof SingleThreadModel) {
  -	    synchronized(servlet) {
  -		servlet.service(request, response);
  -	    }
  -	} else {
  -	    servlet.service(request, response);
  -	}
  -
  -	for( int i=cI.length-1; i>=0; i-- ) {
  -	    cI[i].postService( request.getRealRequest() , response.getRealResponse() ); // ignore the error - like in the original code
  -	}
  -    }
  +	Request rrequest=request.getRealRequest();
  +	Response rresponse=rrequest.getResponse();
   
  -    // 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!
  -    protected void waitForDestroy() {
  -	// Wait until there are no outstanding service calls,
  -	// or until 30 seconds have passed (to avoid a hang)
  -	
  -	// XXX wrong logic !
  -	while (serviceCount > 0) {
  -	    try {
  -		wait(30000);
  -		
  -		break;
  -	    } catch (InterruptedException e) { }
  -	}
  +	handleRequest( rrequest, rresponse );
       }
   
  +    
       public String toString() {
   	String toS="Wrapper(" + config.getServletName() + " ";
   	if( servlet!=null ) toS=toS+ "S:" + servlet.getClass().getName();
  
  
  
  1.4       +38 -7     jakarta-tomcat/src/share/org/apache/tomcat/request/SecurityCheck.java
  
  Index: SecurityCheck.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SecurityCheck.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SecurityCheck.java	2000/02/16 00:48:45	1.3
  +++ SecurityCheck.java	2000/02/17 07:52:21	1.4
  @@ -81,12 +81,43 @@
       public SecurityCheck() {
       }
   	
  +    public void contextInit( Context ctx)
  +	throws TomcatException
  +    {
  +	if( "FORM".equals( ctx.getAuthMethod() )) {
  +	    ServletWrapper jcheck=new ServletWrapper();
  +	    jcheck.setContext( ctx );
  +	    jcheck.setServletClass( "org.apache.tomcat.servlets.JSecurityCheck" );
  +	    jcheck.setServletName( "tomcat.jcheck");
  +	    ctx.addServlet( jcheck );
  +	    
  +	    // If you understand the spec you'll understand the code.
  +	    // I don't understand the spec enough, so I can't comment the code 
  +
  +	    String form=ctx.getFormLoginPage();
  +	    ctx.log( "Adding form login " + form );
  +	    if( form!= null ) {
  +		int lastS=form.lastIndexOf( "/" );
  +		if( lastS<=0 ) {
  +		    ctx.addServletMapping( "/j_security_check", "tomcat.jcheck" );
  +		    ctx.log( "Map  /j_security_check to tomcat.jcheck" );
  +		}  else {
  +		    String dir=form.substring( 0, lastS);
  +		    ctx.addServletMapping( dir + "/j_security_check", "tomcat.jcheck");
  +		    ctx.log( "Map " + dir + "/j_security_check to tomcat.jcheck");
  +		}
  +	    }
  +	}
  +    }
  +	    
  +
       public int authenticate( Request req, Response response )
       {
   	Context ctx=req.getContext();
   	if( req.getRemoteUser() != null) return 0; // already authenticated
   
   	String authMethod=ctx.getAuthMethod();
  +	//	if( ctx.getDebug() > 0 ) ctx.log( "Auth: " + authMethod );
   	if( authMethod==null || "BASIC".equals(authMethod) ) {
   	    String authorization = req.getHeader("Authorization");
   	    // XXX we may have multiple headers ?
  @@ -101,7 +132,7 @@
   		String password = unencoded.substring(colon + 1);
   		if( checkPassword( username, password ) ) {
   		    req.setRemoteUser( username );
  -		    if( ctx.getDebug() > 0 ) ctx.log( "BASEIC Auth:  " + username );
  +		    if( ctx.getDebug() > 0 ) ctx.log( "BASIC Auth:  " + username );
   		} else {
   		    // wrong password
   		    errorPage( req, response );
  @@ -120,16 +151,16 @@
   	    HttpSession session=req.getSession( false );
   	    if( session == null )
   		return 0; // not authenticated
  -	    String username=(String)session.getAttribute( "j_username" );
  -	    String password=(String)session.getAttribute( "j_password" );
  +	    String username=(String)session.getAttribute("j_username");
  +	    String password=(String)session.getAttribute("j_password");
  +	    
  +	    if( ctx.getDebug() > 0 ) ctx.log( "Form Auth:  " + username + " " + password);
   	    if( checkPassword( username, password ) ) {
   		req.setRemoteUser( username );
  -		if( ctx.getDebug() > 0 ) ctx.log( "Form Auth:  " + username );
   	    } else {
  -		// wrong password and user
  +		// wrong password
   		errorPage( req, response );
   	    }
  -	    if( ctx.getDebug() > 0 ) ctx.log( "FORM auth " + username + " " + password );
   	}
   
   	return 0;
  @@ -160,7 +191,7 @@
   	    }
   	}
   
  -	if( ctx.getDebug() > 0 ) ctx.log( "Unauthorized " );
  +	if( ctx.getDebug() > 0 ) ctx.log( "Unauthorized " + user);
    	return HttpServletResponse.SC_UNAUTHORIZED;
   	// XXX check transport
       }
  
  
  
  1.16      +4 -3      jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java
  
  Index: Ajp11ConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- Ajp11ConnectionHandler.java	2000/02/11 02:21:48	1.15
  +++ Ajp11ConnectionHandler.java	2000/02/17 07:52:21	1.16
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.15 2000/02/11 02:21:48 costin Exp $
  - * $Revision: 1.15 $
  - * $Date: 2000/02/11 02:21:48 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.16 2000/02/17 07:52:21 costin Exp $
  + * $Revision: 1.16 $
  + * $Date: 2000/02/17 07:52:21 $
    *
    * ====================================================================
    *
  @@ -111,6 +111,7 @@
   	    //	    RequestImpl request=new RequestImpl();
   	    
   	    AJPRequestAdapter reqA = new AJPRequestAdapter(socket); // todo: clean ConnectionHandler, make it abstract
  +	    reqA.setContextManager( contextM );
   	    //request.setRequestAdapter( reqA );
   	    
   	    Ajp11ResponseAdapter resA=new Ajp11ResponseAdapter();
  
  
  
  1.14      +1 -0      jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java
  
  Index: Ajp12ConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- Ajp12ConnectionHandler.java	2000/02/11 02:21:48	1.13
  +++ Ajp12ConnectionHandler.java	2000/02/17 07:52:22	1.14
  @@ -110,6 +110,7 @@
   
   	    //	    RequestImpl request = new RequestImpl();
   	    AJP12RequestAdapter reqA = new AJP12RequestAdapter(contextM, socket);
  +	    reqA.setContextManager( contextM );
   	    //	    ResponseImpl response=new ResponseImpl();
   	    AJP12ResponseAdapter resA=new AJP12ResponseAdapter();
   
  
  
  
  1.7       +4 -3      jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp23ConnectionHandler.java
  
  Index: Ajp23ConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp23ConnectionHandler.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Ajp23ConnectionHandler.java	2000/01/15 23:30:24	1.6
  +++ Ajp23ConnectionHandler.java	2000/02/17 07:52:22	1.7
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp23ConnectionHandler.java,v 1.6 2000/01/15 23:30:24 costin Exp $
  - * $Revision: 1.6 $
  - * $Date: 2000/01/15 23:30:24 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp23ConnectionHandler.java,v 1.7 2000/02/17 07:52:22 costin Exp $
  + * $Revision: 1.7 $
  + * $Date: 2000/02/17 07:52:22 $
    *
    * ====================================================================
    *
  @@ -108,6 +108,7 @@
   	    ConnectorResponse rresponse=new ConnectorResponse(con);
   	    //	    RequestImpl  rrequest=new RequestImpl();
   	    ConnectorRequest  reqA=new ConnectorRequest(con);
  +	    reqA.setContextManager( contextM );
   	    //rrequest.setRequestAdapter( reqA ); 
   
   	    boolean moreRequests=true;
  
  
  
  1.2       +4 -3      jakarta-tomcat/src/share/org/apache/tomcat/service/connector/JNIConnectionHandler.java
  
  Index: JNIConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/JNIConnectionHandler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- JNIConnectionHandler.java	2000/02/09 12:00:53	1.1
  +++ JNIConnectionHandler.java	2000/02/17 07:52:22	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/JNIConnectionHandler.java,v 1.1 2000/02/09 12:00:53 rubys Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/02/09 12:00:53 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/JNIConnectionHandler.java,v 1.2 2000/02/17 07:52:22 costin Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/02/17 07:52:22 $
    *
    * ====================================================================
    *
  @@ -100,6 +100,7 @@
   
           try {
       	    JNIRequestAdapter reqA = new JNIRequestAdapter(contextM, this);
  +	    reqA.setContextManager( contextM );
       	    JNIResponseAdapter resA =new JNIResponseAdapter(this);
   
       	    reqA.setResponse(resA);
  
  
  
  1.12      +4 -3      jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java
  
  Index: HttpConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- HttpConnectionHandler.java	2000/01/15 23:30:26	1.11
  +++ HttpConnectionHandler.java	2000/02/17 07:52:23	1.12
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java,v 1.11 2000/01/15 23:30:26 costin Exp $
  - * $Revision: 1.11 $
  - * $Date: 2000/01/15 23:30:26 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java,v 1.12 2000/02/17 07:52:23 costin Exp $
  + * $Revision: 1.12 $
  + * $Date: 2000/02/17 07:52:23 $
    *
    * ====================================================================
    *
  @@ -110,6 +110,7 @@
   	    OutputStream out=socket.getOutputStream();
   	    //	    RequestImpl request=new RequestImpl();
   	    HttpRequestAdapter reqA=new HttpRequestAdapter();
  +	    reqA.setContextManager( contextM );
   	    //	    ResponseImpl response=new ResponseImpl();
   	    HttpResponseAdapter resA=new HttpResponseAdapter();
   	    
  
  
  
  1.2       +29 -1     jakarta-tomcat/src/share/org/apache/tomcat/servlets/AuthServlet.java
  
  Index: AuthServlet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/servlets/AuthServlet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AuthServlet.java	2000/02/16 00:30:30	1.1
  +++ AuthServlet.java	2000/02/17 07:52:24	1.2
  @@ -79,10 +79,38 @@
   	throws ServletException, IOException
       {
   	Request req=((HttpServletRequestFacade)request).getRealRequest();
  +	Context ctx=req.getContext();
  +	String realm=ctx.getRealmName();
  +	if( "FORM".equals( ctx.getAuthMethod() )) {
  +	    // the code is not uglier that the spec, we are just implementing it.
  +	    // if you don't understand what's here - you're not alone !
  +	    // ( it helps to  read the spec > 10 times !)
   
  -	String realm=req.getContext().getRealmName();
  +	    String page=ctx.getFormLoginPage();
  +	    if(page!=null) {
  +		HttpSession session=request.getSession( true );
  +		// Because of _stupid_ "j_security_check" we have
  +		// to start the session ( since login page migh not do it ),
  +		// then save the current page ( since we'll have to return here
  +		// and the obvious  solution is too ... simple, and we need to
  +		// do something realy complex ).
  +
  +		// We can't forward to the page - because we set some headers in getSession
  +		// 		RequestDispatcher rd= ctx.getRequestDispatcher( page );
  +		// 		rd.include( request, response );
  +
  +		session.setAttribute( "tomcat.auth.originalLocation", req.getRequestURI());
  +		ctx.log("Setting orig location " + req.getRequestURI());
  +		if( ! page.startsWith("/")) page="/" + page;
  +		response.sendRedirect( ctx.getPath() + page );
  +		return; 
  +	    }
  +	}
  +
  +	// Default is BASIC
   	if(realm==null) realm="default";
   	response.setHeader( "WWW-Authenticate", "Basic \"" + realm + "\"");
   	response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
       }
  +
   }
  
  
  
  1.4       +1 -1      jakarta-tomcat/src/share/org/apache/tomcat/servlets/DefaultErrorPage.java
  
  Index: DefaultErrorPage.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/servlets/DefaultErrorPage.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DefaultErrorPage.java	2000/02/16 17:13:25	1.3
  +++ DefaultErrorPage.java	2000/02/17 07:52:24	1.4
  @@ -92,7 +92,7 @@
   	int status=response.getStatus();
   	String msg=(String)request.getAttribute("javax.servlet.error.message");
   
  -	Throwable e= (Throwable)request.getAttribute("tomcat.error.throwable");
  +	Throwable e= (Throwable)request.getAttribute("tomcat.servlet.error.throwable");
   	if( e!=null ) {
   	    sendError(request, response, 500, exceptionString( e ));
   	    return;
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/servlets/JSecurityCheck.java
  
  Index: JSecurityCheck.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.servlets;
  
  import org.apache.tomcat.util.*;
  import org.apache.tomcat.core.*;
  import java.io.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  
  
  /**
   * Will authenticate the request for non-form auth
   * ( sort of "default form auth" );
   *
   */
  public class JSecurityCheck extends HttpServlet {
      
      public void service(HttpServletRequest request,
  			HttpServletResponse response)
  	throws ServletException, IOException
      {
  	Request req=((HttpServletRequestFacade)request).getRealRequest();
  	Context ctx=req.getContext();
  	ctx.log( "In JSecurityCheck");
  	HttpSession session=req.getSession( false );
  	if( session == null ) {
  	    ctx.log("TRY TO AUTHENTICATE WITHOUT A SESSION " + req);
  	    return;
  	}
  	String username=req.getFacade().getParameter( "j_username" );
  	String password=req.getFacade().getParameter( "j_password" );
  	if( ctx.getDebug() > 0 ) ctx.log( "FORM auth " + username + " " + password );
  
  	session.setAttribute( "j_username", username );
  	session.setAttribute( "j_password", password );
  
  	String origLocation=(String)session.getAttribute( "tomcat.auth.originalLocation");
  	ctx.log("Back to orig location " + origLocation);
  	response.sendRedirect( origLocation );
      }
  
  }