tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@locus.apache.org
Subject cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util PrefixMapper.java
Date Mon, 19 Jun 2000 21:53:16 GMT
costin      00/06/19 14:53:16

  Modified:    src/share/org/apache/tomcat/context DefaultCMSetter.java
               src/share/org/apache/tomcat/core Context.java
                        ContextManager.java Handler.java Request.java
                        RequestImpl.java ResponseImpl.java
                        ServletWrapper.java
               src/share/org/apache/tomcat/facade
                        HttpServletRequestFacade.java
                        HttpServletResponseFacade.java
                        RequestDispatcherImpl.java
               src/share/org/apache/tomcat/loader AdaptiveClassLoader.java
                        AdaptiveClassLoader12.java
                        AdaptiveServletLoader.java
               src/share/org/apache/tomcat/request AccessInterceptor.java
                        SimpleRealm.java
               src/share/org/apache/tomcat/startup EmbededTomcat.java
               src/share/org/apache/tomcat/util PrefixMapper.java
  Log:
  Few changes in error handling.
  - avoid Request-facade-request transformations and multiple layers.
  - avoid mux/demux for errors - use a different handler for each case
  instead of a single ErrorServlet
  
  The new handlers are part of DefaultCMSetter, which sets the defaults for the
  context. You can override them with normal servlets ( by re-defining the handler
  names ), but unless the application is "trusted" it can't access internal objects.
  
  The error processing is still a bit complex, but at least we have fewer layers and it's
  easier to debug.
  
  Also, implemented FORM based login ( finally ) - it seems to work fine ( including Pet Store!).
  
  - added more debug messages, traces - I spend a lot of time hunting "link errors" in class
  loader.
  
  Revision  Changes    Path
  1.41      +273 -21   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.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- DefaultCMSetter.java	2000/06/16 21:02:38	1.40
  +++ DefaultCMSetter.java	2000/06/19 21:53:10	1.41
  @@ -69,9 +69,11 @@
   import java.util.*;
   import java.security.*;
   import javax.servlet.http.*;
  +import javax.servlet.*;
   
   import org.apache.tomcat.logging.*;
   
  +
   /**
    * Check ContextManager and set defaults for non-set properties
    *
  @@ -88,24 +90,15 @@
   	setEngineHeader( ctx );
   
   
  -	// XXX XXX this will go away - error handling needs to
  -	// be re-writen !!!!!! 
  -	ServletWrapper errorWrapper=new ServletWrapper();
  -	errorWrapper.setContext( ctx );
  -	errorWrapper.setServletClass( "org.apache.tomcat.servlets.DefaultErrorPage" );
  -	errorWrapper.setServletName( "tomcat.errorPage");
  -	ctx.addServlet( errorWrapper );
  -
  -	// Validation for error  servlet
  - 	try {
  -	    ServletWrapper errorWrapper1=ctx.getServletByName( "tomcat.errorPage");
  -	    errorWrapper1.init();
  -	} catch( Exception ex ) {
  -	    System.out.println("Error loading default servlet ");
  -            ex.printStackTrace();
  -	    // XXX remove this context from CM
  -	    throw new TomcatException( "Error loading default error servlet ", ex );
  -	}
  +	ctx.addServlet( new ExceptionHandler());
  +	ctx.addServlet( new StatusHandler());
  +
  +	// Default status handlers
  +	ctx.addServlet( new RedirectHandler());
  +	ctx.addErrorPage( "302", "tomcat.redirectHandler");
  +	ctx.addServlet( new NotFoundHandler());
  +	ctx.addErrorPage( "404", "tomcat.notFoundHandler");
  +	
       }
   
       // -------------------- implementation
  @@ -122,10 +115,13 @@
   	    // no longer use core.properties - the configuration comes from
   	    // server.xml or web.xml - no more properties.
   	    StringBuffer sb=new StringBuffer();
  -	    sb.append(Constants.TOMCAT_NAME).append("/").append(Constants.TOMCAT_VERSION);
  -	    sb.append(" (").append(Constants.JSP_NAME).append(" ").append(Constants.JSP_VERSION);
  +	    sb.append(Constants.TOMCAT_NAME).append("/");
  +	    sb.append(Constants.TOMCAT_VERSION);
  +	    sb.append(" (").append(Constants.JSP_NAME).append(" ");
  +	    sb.append(Constants.JSP_VERSION);
   	    sb.append("; ").append(Constants.SERVLET_NAME).append(" ");
  -	    sb.append(Constants.SERVLET_MAJOR).append(".").append(Constants.SERVLET_MINOR);
  +	    sb.append(Constants.SERVLET_MAJOR).append(".");
  +	    sb.append(Constants.SERVLET_MINOR);
   	    sb.append( "; Java " );
   	    sb.append(System.getProperty("java.version")).append("; ");
   	    sb.append(System.getProperty("os.name") + " ");
  @@ -137,4 +133,260 @@
   	ctx.setEngineHeader( engineHeader );
       }
   
  +}
  +
  +class NotFoundHandler extends ServletWrapper {
  +    static StringManager sm=StringManager.
  +	getManager("org.apache.tomcat.servlets");
  +
  +    NotFoundHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.notFoundHandler";
  +    }
  +
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	res.setContentType("text/html");	// ISO-8859-1 default
  +
  +	StringBuffer buf = new StringBuffer();
  +	buf.append("<head><title>")
  +	    .append(sm.getString("defaulterrorpage.notfound404"))
  +	    .append("</title></head>\r\n");
  +	buf.append("<body><h1>")
  +	    .append(sm.getString("defaulterrorpage.notfound404"))
  +	    .append("</h1>\r\n");
  +	buf.append(sm.getString("defaulterrorpage.originalrequest"))
  +	    .append( req.getRequestURI());
  +	buf.append("</body>\r\n");
  +
  +	String body = buf.toString();
  +
  +	res.setContentLength(body.length());
  +
  +	if( res.isUsingStream() ) {
  +	    ServletOutputStream out = res.getOutputStream();
  +	    out.print(body);
  +	    out.flush();
  +	} else {
  +	    PrintWriter out = res.getWriter();
  +	    out.print(body);
  +	    out.flush();
  +	}
  +    }
  +}
  +
  +class ExceptionHandler extends ServletWrapper {
  +    static StringManager sm=StringManager.
  +	getManager("org.apache.tomcat.servlets");
  +
  +    ExceptionHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.exceptionHandler";
  +    }
  +
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	String msg=(String)req.getAttribute("javax.servlet.error.message");
  +	
  +	Throwable e= (Throwable)req.
  +	    getAttribute("tomcat.servlet.error.throwable");
  +	if( e==null ) {
  +	    System.out.println("ASSERT: Exception handler without exception");
  +	    /*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
  +	    return;
  +	}
  +
  +	res.setContentType("text/html");
  +	res.setStatus( 500 );
  +	
  +	StringBuffer buf = new StringBuffer();
  +	buf.append("<h1>");
  +	if( res.isIncluded() ) {
  +	    buf.append(sm.getString("defaulterrorpage.includedservlet") );
  +	}  else {
  +	    buf.append("Error: ");
  +	}
  +	
  +	buf.append( 500 );
  +	buf.append("</h1>\r\n");
  +
  +	// More info - where it happended"
  +	buf.append("<h2>")
  +	    .append(sm.getString("defaulterrorpage.location"))
  +	    .append(req.getRequestURI())
  +	    .append("</h2>");
  +
  +	buf.append("<b>")
  +	    .append(sm.getString("defaulterrorpage.internalservleterror"))
  +	    .append("</b><br>");
  +        buf.append("<pre>");
  +
  +	StringWriter sw = new StringWriter();
  +	PrintWriter pw = new PrintWriter(sw);
  +	e.printStackTrace(pw);
  +
  +	buf.append(sw.toString());
  +
  +	buf.append("</pre>\r\n");
  +
  +        if (e instanceof ServletException) {
  +	    Throwable cause = ((ServletException)e).getRootCause();
  +	    if (cause != null) {
  +		buf.append("<b>")
  +		    .append(sm.getString("defaulterrorpage.rootcause"))
  +		    .append("</b>\r\n");
  +	    buf.append("<pre>");
  +
  +	    sw=new StringWriter();
  +	    pw=new PrintWriter(sw);
  +	    cause.printStackTrace( pw );
  +	    buf.append( sw.toString());
  +
  +	    buf.append("</pre>\r\n");
  +	    }
  +	}
  +	
  +	buf.append("\r\n");
  +	
  +	if( res.isUsingStream() ) {
  +	    ServletOutputStream out = res.getOutputStream();
  +	    out.print(buf.toString());
  +	} else {
  +	    PrintWriter out = res.getWriter();
  +	    out.print(buf.toString());
  +	}
  +    }
  +}
  +
  +class StatusHandler extends ServletWrapper {
  +    static StringManager sm=StringManager.
  +	getManager("org.apache.tomcat.servlets");
  +
  +    StatusHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.statusHandler";
  +    }
  +    
  +    // We don't want interceptors called for redirect
  +    // handler
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	String msg=(String)req.getAttribute("javax.servlet.error.message");
  +	
  +	res.setContentType("text/html");
  +	// res is reset !!!
  +	// status is already set
  +	int sc=res.getStatus();
  +	
  +	StringBuffer buf = new StringBuffer();
  +	buf.append("<h1>");
  +	if( res.isIncluded() ) {
  +	    buf.append(sm.getString("defaulterrorpage.includedservlet") );
  +	}  else {
  +	    buf.append("Error: ");
  +	}
  +	
  +	buf.append( sc );
  +	buf.append("</h1>\r\n");
  +
  +	// More info - where it happended"
  +	buf.append("<h2>")
  +	    .append(sm.getString("defaulterrorpage.location"))
  +	    .append(req.getRequestURI())
  +	    .append("</h2>");
  +
  +	buf.append("<b>")
  +	    .append(msg)
  +	    .append("</b><br>");
  +
  +	if( res.isUsingStream() ) {
  +	    ServletOutputStream out = res.getOutputStream();
  +	    out.print(buf.toString());
  +	} else {
  +	    PrintWriter out = res.getWriter();
  +	    out.print(buf.toString());
  +	}
  +    }
  +}
  +	
  +class RedirectHandler extends ServletWrapper {
  +    static StringManager sm=StringManager.
  +	getManager("org.apache.tomcat.servlets");
  +
  +    RedirectHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.redirectHandler";
  +    }
  +
  +    // We don't want interceptors called for redirect
  +    // handler
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	String location	= (String)
  +	    req.getAttribute("javax.servlet.error.message");
  +	Context ctx=req.getContext();
  +	
  +	location = makeAbsolute(req, location);
  +
  +	ctx.log("Redirect " + location + " " + req );
  +
  +	res.setContentType("text/html");	// ISO-8859-1 default
  +	res.setHeader("Location", location);
  +
  +	StringBuffer buf = new StringBuffer();
  +	buf.append("<head><title>").
  +	    append(sm.getString("defaulterrorpage.documentmoved")).
  +	    append("</title></head>\r\n<body><h1>").
  +	    append(sm.getString("defaulterrorpage.documentmoved")).
  +	    append("</h1>\r\n").
  +	    append(sm.getString("defaulterrorpage.thisdocumenthasmoved")).
  +	    append(" <a href=\"").
  +	    append(location).
  +	    append("\">here</a>.<p>\r\n</body>\r\n");
  +
  +	String body = buf.toString();
  +
  +	res.setContentLength(body.length());
  +
  +	if( res.isUsingStream() ) {
  +	    ServletOutputStream out = res.getOutputStream();
  +	    out.print(body);
  +	    out.flush();
  +	} else {
  +	    PrintWriter out = res.getWriter();
  +	    out.print(body);
  +	    out.flush();
  +	}
  +    }
  +
  +    private String makeAbsolute(Request req, String location) {
  +        URL url = null;
  +        try {
  +	    // Try making a URL out of the location
  +	    // Throws an exception if the location is relative
  +            url = new URL(location);
  +	} catch (MalformedURLException e) {
  +	    String requrl = HttpUtils.getRequestURL(req.getFacade()).
  +		toString();
  +	    try {
  +	        url = new URL(new URL(requrl), location);
  +	    }
  +	    catch (MalformedURLException ignored) {
  +	        // Give up
  +	        return location;
  +	    }
  +	}
  +        return url.toString();
  +    }
  +
  +
  +    
   }
  
  
  
  1.96      +9 -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.95
  retrieving revision 1.96
  diff -u -r1.95 -r1.96
  --- Context.java	2000/06/16 21:03:20	1.95
  +++ Context.java	2000/06/19 21:53:10	1.96
  @@ -475,6 +475,14 @@
   	return formErrorPage;
       }
   
  +    public void setFormLoginPage( String page ) {
  +	formLoginPage=page;
  +    }
  +    
  +    public void setFormErrorPage( String page ) {
  +	formErrorPage=page;
  +    }
  +
       public void setLoginConfig( String authMethod, String realmName,
   				String formLoginPage, String formErrorPage)
       {
  @@ -625,6 +633,7 @@
       public void addServlet(ServletWrapper wrapper)
       	throws TomcatException
       {
  +	wrapper.setContext( this );
   	String name=wrapper.getServletName();
   	//	System.out.println("Adding servlet " + name  + " " + wrapper);
   
  
  
  
  1.93      +54 -100   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.92
  retrieving revision 1.93
  diff -u -r1.92 -r1.93
  --- ContextManager.java	2000/06/16 21:03:21	1.92
  +++ ContextManager.java	2000/06/19 21:53:10	1.93
  @@ -651,10 +651,10 @@
   		rrequest.getWrapper().service(rrequest, rresponse);
   	    } else {
   		// something went wrong
  -		handleError( rrequest, rresponse, null, status );
  +		handleStatus( rrequest, rresponse, status );
   	    }
   	} catch (Throwable t) {
  -	    handleError( rrequest, rresponse, t, 0 );
  +	    handleError( rrequest, rresponse, t );
   	}
   	try {
   	    rresponse.finish();
  @@ -822,44 +822,33 @@
        */
       public void handleStatus( Request req, Response res, int code ) {
   	String errorPath=null;
  -	ServletWrapper errorServlet=null;
  +	Handler errorServlet=null;
   	
   	res.reset();
  -	res.setStatus(code);
   
  -	Context ctx = req.getContext();
   	if( code==0 )
   	    code=res.getStatus();
  -	if(ctx==null) 
  -	    ctx=getContext("");
  +	else
  +	    res.setStatus(code);
   
  -	if(ctx.getDebug() > 4 ) ctx.log("In error handler for code=" + code +  " / " + req );
  +	Context ctx = req.getContext();
  +	if(ctx==null) ctx=getContext("");
   
  -	ServletWrapper dE = doubleError( ctx, req );
  -	if( dE != null )
  -	    errorServlet = dE;
  -
  -	// normal redirects or non-errors
  -	if( code!=0 && code < 400 ) 
  -	    errorServlet=ctx.getServletByName("tomcat.errorPage");
  -
  -	// we can't support error pages for non-errors, it's to
  -	// complex and insane
  -	if( code >= 400 )
  -	    errorPath = ctx.getErrorPage( code );
  -	    
  -	// Special case - unauthorized
  -	
  -	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( "Calling auth servlet " + errorServlet );
  +	ctx.log( "Status Handler: " + code + " req=" + req);
  +
  +	errorPath = ctx.getErrorPage( code );
  +	if( errorPath != null ) {
  +	    errorServlet=getHandlerForPath( ctx, errorPath );
   	}
  +
  +	if( errorServlet==null )
  +	    errorServlet=ctx.getServletByName( "tomcat.statusHandler");
  +
   	req.setAttribute("javax.servlet.error.status_code",new Integer( code));
   
  -	//	System.out.println("XXX " + req + " " + res + " " + ctx );
  -	callInternalError( req, res, ctx, errorServlet, errorPath );
  +	req.setAttribute("tomcat.servlet.error.request", req);
  +
  +	errorServlet.service( req, res );
       }
   
       /** General error handling mechanism. It will try to find an error handler
  @@ -870,15 +859,16 @@
   	if(ctx==null) {
   	    ctx=getContext("");
   	}
  -	if(ctx.getDebug() > 4 ) ctx.log("In error handler " +  t +  " / " + req );
   
  +	/** The exception must be available to the user.
  +	    Note that it is _WRONG_ to send the trace back to
  +	    the client. AFAIK the trace is the _best_ debugger.
  +	*/
  +	ctx.log("Exception in: " + req , t );
  +	
   	String errorPath=null;
  -	ServletWrapper errorServlet=null;
  +	Handler errorServlet=null;
   
  -	ServletWrapper dE = doubleError( ctx, req );
  -	if( dE != null )
  -	    errorServlet = dE;
  -	
   	// Scan the exception's inheritance tree looking for a rule
   	// that this type of exception should be forwarded
   	Class clazz = t.getClass();
  @@ -887,88 +877,52 @@
   	    errorPath = ctx.getErrorPage(name);
   	    clazz = clazz.getSuperclass();
   	}
  +	
  +	if( errorPath != null ) {
  +	    errorServlet=getHandlerForPath( ctx, errorPath );
  +	}
   
  +	if( errorLoop( ctx, req ) || errorServlet==null) ;
  +	    errorServlet = ctx.getServletByName("tomcat.exceptionHandler");
  +	
   	req.setAttribute("javax.servlet.error.exception_type", t.getClass());
   	req.setAttribute("javax.servlet.error.message", t.getMessage());
   	req.setAttribute("tomcat.servlet.error.throwable", t);
  +	req.setAttribute("tomcat.servlet.error.request", req);
   
  -	callInternalError( req, res, ctx, errorServlet, errorPath );
  +	errorServlet.service( req, res );
       }
   
  -    private void callInternalError( Request req, Response res, Context ctx,
  -			       ServletWrapper errorServlet, String errorPath )
  -    {
  -	// 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( errorPath==null && errorServlet==null) {
  -	    // this is the default handler -  avoid loops
  -	    req.setAttribute( "tomcat.servlet.error.defaultHandler", "true");
  -	    errorServlet=ctx.getServletByName("tomcat.errorPage");
  -	}
  -		
  -	// Try a normal "error page" ( path based )
  -	if( errorServlet==null && errorPath != null ) {
  -	    try {
  -		RequestDispatcher rd = ctx.getFacade().getRequestDispatcher(errorPath);
  -		// reset the response, keeping the status code if necessary
  -		// try a forward if possible, otherwise an include
  -		if (res.isBufferCommitted()) {
  -		    rd.include(req.getFacade(), res.getFacade());
  -                }
  -		else {
  -		    rd.forward(req.getFacade(), res.getFacade());
  -                }
  -		return ;
  -	    } catch( Throwable t1 ) {
  -		ctx.log(" Error in custom error handler " + t1 );
  -		// nothing - we'll call DefaultErrorPage
  -	    }
  +    public Handler getHandlerForPath( Context ctx, String path ) {
  +	if( ! path.startsWith( "/" ) ) {
  +	    return ctx.getServletByName( path );
   	}
  +	RequestImpl req1=new RequestImpl();
  +	ResponseImpl res1=new ResponseImpl();
  +	initRequest( req1, res1 );
   	
  -	// If No handler or an error happened in handler 
  -	// loop control
  -	if( req.getAttribute("tomcat.servlet.error.handler") != null ) {
  -	    // error page for 404 doesn't exist... ( or watchdog tests :-)
  -	    ctx.log( "Error/loop in default error handler " + req + " " +  errorPath );
  -	    return;
  -	}
  -
  -	if( ctx.getDebug() > 0 ) ctx.log( "Error: Calling servlet " + errorServlet );
  -	req.setAttribute("tomcat.servlet.error.handler", errorServlet);
  -	errorServlet.service(req,res);
  -
  -	return;
  +	req1.setRequestURI( ctx.getPath() + path );
  +	processRequest( req1 );
  +	return req1.getWrapper();
       }
  -
  +    
       /** Handle the case of error handler generating an error or special status
        */
  -    private ServletWrapper doubleError( Context ctx, Request req ) {
  +    private boolean errorLoop( Context ctx, Request req ) {
   	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"));
   
  -	    return ctx.getServletByName("tomcat.errorPage");
  +	    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"));
  +	    
  +	    return true;
   	}
  -	return null;
  +	return false;
       }
       
  -    /** @deprecated old method
  -     */
  -    void handleError( Request req, Response res , Throwable t, int code ) {
  -	if( t!=null )
  -	    handleError( req, res, t );
  -	else
  -	    handleStatus( req, res, code );
  -    }
  -
  -	
   
       // -------------------- Support for notes --------------------
           
  
  
  
  1.3       +37 -13    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.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Handler.java	2000/06/16 21:03:21	1.2
  +++ Handler.java	2000/06/19 21:53:11	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java,v 1.2 2000/06/16 21:03:21 costin Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/06/16 21:03:21 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java,v 1.3 2000/06/19 21:53:11 costin Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/06/19 21:53:11 $
    *
    * ====================================================================
    *
  @@ -110,6 +110,7 @@
       
       // who creates the servlet definition
       protected int origin;
  +    protected boolean internal=false;
   
       public Handler() {
       }
  @@ -123,6 +124,10 @@
   	return context;
       }
   
  +    public boolean isInternal() {
  +	return internal;
  +    }
  +    
       public String getName() {
   	return name;
       }
  @@ -209,14 +214,22 @@
       {
   	try {
   	    if( initialized ) return;
  +	    if( ! (this instanceof ServletWrapper) ) {
  +		doInit();
  +		return;
  +	    }
   	    
   	    ContextInterceptor cI[]=context.getContextInterceptors();
   	    for( int i=0; i<cI.length; i++ ) {
   		try {
  -		    cI[i].preServletInit( context, null);//this );
  +		    cI[i].preServletInit( context, (ServletWrapper)this );
   		    // ignore the error - like in the original code
   		} catch( TomcatException ex) {
   		    ex.printStackTrace();
  +		    if( ex.getRootCause() != null ) {
  +			System.out.println("Original error " );
  +			ex.getRootCause().printStackTrace();
  +		    }
   		}
   	    }
   
  @@ -227,7 +240,7 @@
   		
   	    for( int i=cI.length-1; i>=0; i-- ) {
   		try {
  -		    cI[i].postServletInit( context, null);//this);
  +		    cI[i].postServletInit( context, (ServletWrapper)this);
   		    // ignore the error - like in the original code
   		} catch( TomcatException ex) {
   		    ex.printStackTrace();
  @@ -257,6 +270,10 @@
   		init();
   	    } catch( Exception ex ) {
   		initialized=false;
  +		if( ex instanceof ClassNotFoundException ) {
  +		    contextM.handleStatus( req, res, 404);
  +		    return;
  +		}
   		context.log("Exception in init  " + ex.getMessage(), ex );
   		contextM.handleError( req, res, ex );
   		return;
  @@ -265,11 +282,13 @@
   	
   	// We are initialized and fine
   	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
  +	if( ! internal ) {
  +	    for( int i=0; i<cI.length; i++ ) {
  +		cI[i].preService( req, res );
  +		// ignore the error - like in the original code
  +	    }
   	}
  -
  +	
   	Throwable t=null;
   	try {
   	    doService( req, res );
  @@ -278,12 +297,17 @@
   	}
   	
   	// continue with the postService
  -
  -	for( int i=cI.length-1; i>=0; i-- ) {
  -	    cI[i].postService( req , res );
  -	    // ignore the error - like in the original code
  +	if( ! internal ) {
  +	    for( int i=cI.length-1; i>=0; i-- ) {
  +		cI[i].postService( req , res );
  +		// ignore the error - like in the original code
  +	    }
   	}
  +	
  +	handleError( req, res, t );
  +    }
   
  +    protected void handleError( Request req, Response res, Throwable t) {
   	if( t==null)
   	    return;
   	
  
  
  
  1.44      +2 -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.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- Request.java	2000/05/30 06:16:45	1.43
  +++ Request.java	2000/06/19 21:53:12	1.44
  @@ -241,6 +241,8 @@
        */
       public String[] getParameterValues(String name) ;
   
  +    public String getParameter(String name );
  +    
       public Enumeration getParameterNames() ;
   
       // -------------------- Attributes --------------------
  
  
  
  1.49      +10 -0     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.48
  retrieving revision 1.49
  diff -u -r1.48 -r1.49
  --- RequestImpl.java	2000/06/15 10:15:29	1.48
  +++ RequestImpl.java	2000/06/19 21:53:12	1.49
  @@ -238,6 +238,16 @@
   	lookupPath=l;
       }
   
  +    // XXX optimize for common case ( single params )
  +    public String getParameter(String name ) {
  +	String[] values = getParameterValues(name);
  +        if (values != null) {
  +            return values[0];
  +        } else {
  +	    return null;
  +        }
  +    }
  +    
       public String[] getParameterValues(String name) {
   	handleParameters();
           return (String[])parameters.get(name);
  
  
  
  1.30      +6 -3      jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java
  
  Index: ResponseImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- ResponseImpl.java	2000/05/30 06:16:46	1.29
  +++ ResponseImpl.java	2000/06/19 21:53:12	1.30
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v 1.29 2000/05/30 06:16:46 costin Exp $
  - * $Revision: 1.29 $
  - * $Date: 2000/05/30 06:16:46 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v 1.30 2000/06/19 21:53:12 costin Exp $
  + * $Revision: 1.30 $
  + * $Date: 2000/06/19 21:53:12 $
    *
    * ====================================================================
    *
  @@ -368,6 +368,9 @@
   
       public void setBufferCommitted( boolean v ) {
   	this.commited=v;
  +	// 	System.out.println("Buffer commited " );
  +	// 	/*DEBUG*/ try {throw new Exception(); }
  +	//catch(Exception ex) {ex.printStackTrace();}
       }
       
       public void reset() throws IllegalStateException {
  
  
  
  1.55      +5 -8      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.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- ServletWrapper.java	2000/06/16 21:03:22	1.54
  +++ ServletWrapper.java	2000/06/19 21:53:12	1.55
  @@ -106,7 +106,7 @@
       // is running ( this have to be revisited !) 
       protected long lastAccessed;
       protected int serviceCount = 0;
  -
  +    
       int loadOnStartup=0;
   
       Hashtable securityRoleRefs=new Hashtable();
  @@ -138,8 +138,7 @@
       }
   
       public String getServletName() {
  -	if( servletName != null ) return servletName;
  -	if( servletClassName != null ) return servletClassName;
  +	if(name!=null) return name;
   	return path;
       }
   
  @@ -152,9 +151,9 @@
           return this.description;
       }
   
  -//     public void setDescription( String d ) {
  -// 	description=d;
  -//     }
  +    public void setDescription( String d ) {
  +	description=d;
  +    }
       
       public void setServletDescription(String description) {
           this.description = description;
  @@ -194,8 +193,6 @@
   
       // -------------------- 
   
  -    // XXX Doesn't seem to be used, shouldn't be part of interface -
  -    // use init and service !!! 
       public Servlet getServlet() {
   	if(servlet==null) {
   	    try {
  
  
  
  1.6       +1 -6      jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletRequestFacade.java
  
  Index: HttpServletRequestFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletRequestFacade.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- HttpServletRequestFacade.java	2000/05/30 15:40:09	1.5
  +++ HttpServletRequestFacade.java	2000/06/19 21:53:13	1.6
  @@ -219,12 +219,7 @@
       /** Adapter: Request doesn't deal with this servlet convention
        */
       public String getParameter(String name) {
  -        String[] values = getParameterValues(name);
  -        if (values != null) {
  -            return values[0];
  -        } else {
  -	    return null;
  -        }
  +        return request.getParameter( name );
       }
   
       public String[] getParameterValues(String name) {
  
  
  
  1.6       +14 -8     jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletResponseFacade.java
  
  Index: HttpServletResponseFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletResponseFacade.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- HttpServletResponseFacade.java	2000/06/10 19:05:10	1.5
  +++ HttpServletResponseFacade.java	2000/06/19 21:53:13	1.6
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletResponseFacade.java,v 1.5 2000/06/10 19:05:10 craigmcc Exp $
  - * $Revision: 1.5 $
  - * $Date: 2000/06/10 19:05:10 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletResponseFacade.java,v 1.6 2000/06/19 21:53:13 costin Exp $
  + * $Revision: 1.6 $
  + * $Date: 2000/06/19 21:53:13 $
    *
    * ====================================================================
    *
  @@ -196,12 +196,18 @@
       }
       
       public void sendError(int sc, String msg) throws IOException {
  -	if (isCommitted())
  -	    throw new IllegalStateException(sm.getString("hsrf.error.ise"));
  -
  -	else if (sc != HttpServletResponse.SC_UNAUTHORIZED)	// CRM: FIXME
  -	    response.resetBuffer(); // Keep headers and cookies that are set
  +	if (isCommitted()) {
  +	    Context ctx=response.getRequest().getContext();
  +	    ctx.log( "Servlet API error: sendError with commited buffer ");
  +	    // 	    /*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
  +	    throw new IllegalStateException(sm.
  +					    getString("hsrf.error.ise"));
  +	}
   
  +	// 	if (sc != HttpServletResponse.SC_UNAUTHORIZED)	// CRM: FIXME
  +	// 	    response.resetBuffer();
  +	// Keep headers and cookies that are set
  +	
   	setStatus( sc );
   	Request request=response.getRequest();
   	request.setAttribute("javax.servlet.error.message", msg);
  
  
  
  1.5       +2 -1      jakarta-tomcat/src/share/org/apache/tomcat/facade/RequestDispatcherImpl.java
  
  Index: RequestDispatcherImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/RequestDispatcherImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RequestDispatcherImpl.java	2000/06/19 16:29:25	1.4
  +++ RequestDispatcherImpl.java	2000/06/19 21:53:14	1.5
  @@ -99,7 +99,8 @@
    */
   final class RequestDispatcherImpl implements RequestDispatcher {
       // Use the strings from core
  -    private static StringManager sm = StringManager.getManager("org.apache.tomcat.core");
  +    private static StringManager sm = StringManager.
  +	getManager("org.apache.tomcat.core");
       
       Context context;
       // path dispatchers
  
  
  
  1.9       +43 -40    jakarta-tomcat/src/share/org/apache/tomcat/loader/AdaptiveClassLoader.java
  
  Index: AdaptiveClassLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/loader/AdaptiveClassLoader.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- AdaptiveClassLoader.java	2000/06/15 18:50:43	1.8
  +++ AdaptiveClassLoader.java	2000/06/19 21:53:14	1.9
  @@ -118,7 +118,7 @@
    * @author Martin Pool
    * @author Jim Heintz
    * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
  - * @version $Revision: 1.8 $ $Date: 2000/06/15 18:50:43 $
  + * @version $Revision: 1.9 $ $Date: 2000/06/19 21:53:14 $
    * @see java.lang.ClassLoader
    */
   public class AdaptiveClassLoader extends ClassLoader {
  @@ -145,7 +145,7 @@
        * Cache of the loaded classes. This contains ClassCacheEntry keyed
        * by class names.
        */
  -    private Hashtable cache;
  +    protected Hashtable cache;
   
       /**
        * The classpath which this classloader searches for class definitions.
  @@ -211,14 +211,13 @@
        *        a valid directory or a zip/jar file.
        */
       public AdaptiveClassLoader() {
  +	// Create the cache of loaded classes
  +	cache = new Hashtable();
       }
   
       public void setRepository( Vector classRepository ) 
   	throws IllegalArgumentException
       {
  -	// Create the cache of loaded classes
  -	cache = new Hashtable();
  -	
   	// Verify that all the repository are valid.
   	Enumeration e = classRepository.elements();
   	while(e.hasMoreElements()) {
  @@ -262,12 +261,6 @@
               }
           }
   
  -       // Install the SecurityManager if not already installed
  -	//        if( generationCounter == 0 && sm == null ) {
  -	//            sm = System.getSecurityManager();
  -	// 	   //	   System.out.println("XXX AdaptiveClassLoader: " + sm );
  -	//        }
  -
           // Store the class repository for use
           this.repository = classRepository;
   
  @@ -349,9 +342,13 @@
           Enumeration e = cache.elements();
           while (e.hasMoreElements()) {
               ClassCacheEntry entry = (ClassCacheEntry) e.nextElement();
  -
  -        if (entry.isSystemClass()) continue;
   
  +	    if( entry.loadedClass==null )
  +		continue;
  +	    if( debug>5 )
  +		log( "cache entry: " + entry.loadedClass.getName());
  +	    if (entry.isSystemClass()) continue;
  +	    
               // XXX: Because we want the classloader to be an accurate
               // reflection of the contents of the repository, we also
               // reload if a class origin file is now missing.  This
  @@ -426,6 +423,7 @@
           ClassCacheEntry entry = (ClassCacheEntry) cache.get(name);
   
           if (entry != null) {
  +	    if( debug>0) log( "Found in cache " + name);
               // Class found in our cache
               c = entry.loadedClass;
               if (resolve) resolveClass(c);
  @@ -435,13 +433,15 @@
           // Make sure we can access this class when using a SecurityManager
           if (sm != null) {
               int i = name.lastIndexOf('.');
  -            if (i >= 0)
  -                sm.checkPackageAccess(name.substring(0,i));
  -        }
  +            if (i >= 0) {
  +                sm.checkPackageAccess(name.substring(0,i)); 
  +                sm.checkPackageDefinition(name.substring(0,i));
  +	    }
  +	}
   
   	if (parent != null) {
   	    try {
  -		if( debug>0) log( "loadClass() from parent" + name);
  +		if( debug>0) log( "loadClass() from parent " + name);
   		c = parent.loadClass(name);
   		if (c != null) {
   		    if (resolve) resolveClass(c);
  @@ -455,7 +455,7 @@
   	}
   
           // Attempt to load the class from the system
  -	if( debug>0) log( "loadClass() from system" + name);
  +	if( debug>0) log( "loadClass() from system " + name);
           try {
               c = loadSystemClass(name, resolve);
               if (c != null) {
  @@ -465,14 +465,7 @@
               c = null;
           }
   
  -        // Make sure we can define this class when using a SecurityManager
  -        if (sm != null) {
  -            int i = name.lastIndexOf('.');
  -            if (i >= 0)
  -                sm.checkPackageDefinition(name.substring(0,i));
  -        }
  -
  -		if( debug>0) log( "loadClass() from local repository " + name);
  +	if( debug>0) log( "loadClass() from local repository " + name);
           // Try to load it from each repository
           Enumeration repEnum = repository.elements();
   
  @@ -502,17 +495,27 @@
   	    }
   
               if (classData != null) {
  -                // Define the class with a ProtectionDomain if using a SecurityManager
  -                c=doDefineClass(name, classData, cp.getProtectionDomain());
  -                // Cache the result;
  -                classCache.loadedClass = c;
  +                // Define the class with a ProtectionDomain if using
  +		// a SecurityManager
                   // Origin is set by the specific loader
                   classCache.lastModified = classCache.origin.lastModified();
  -                cache.put(name, classCache);
  -    
  +		if( debug>0) log( "Add to cache() " + name + " " + classCache);
  +		cache.put(name, classCache);
  +		
  +		if( debug>0) log( "Before define class " + name);
  +		try {
  +		    classCache.loadedClass = 
  +			doDefineClass(name, classData,
  +				      cp.getProtectionDomain());
  +		} catch(Throwable t ) {
  +		    t.printStackTrace();
  +		}
  +		if( debug>0) log( "Class defined " + classCache.loadedClass);
  +                // Cache the result;
  +
                   // Resolve it if necessary
  -		if (resolve) resolveClass(c);
  -                return c;
  +		if (resolve) resolveClass(classCache.loadedClass);
  +                return classCache.loadedClass;
               }
           }
   
  @@ -540,12 +543,12 @@
           Class c = findSystemClass(name);
           // Throws if not found.
   
  -        // Add cache entry
  -        ClassCacheEntry cacheEntry = new ClassCacheEntry();
  -        cacheEntry.origin = null;
  -        cacheEntry.loadedClass = c;
  -        cacheEntry.lastModified = Long.MAX_VALUE;
  -        cache.put(name, cacheEntry);
  +//         // Add cache entry
  +//         ClassCacheEntry cacheEntry = new ClassCacheEntry();
  +//         cacheEntry.origin = null;
  +//         cacheEntry.loadedClass = c;
  +//         cacheEntry.lastModified = Long.MAX_VALUE;
  +//         cache.put(name, cacheEntry);
   
           if (resolve) resolveClass(c);
   
  
  
  
  1.3       +11 -3     jakarta-tomcat/src/share/org/apache/tomcat/loader/AdaptiveClassLoader12.java
  
  Index: AdaptiveClassLoader12.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/loader/AdaptiveClassLoader12.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AdaptiveClassLoader12.java	2000/06/15 18:50:45	1.2
  +++ AdaptiveClassLoader12.java	2000/06/19 21:53:14	1.3
  @@ -66,7 +66,8 @@
   /** Fixes for 1.2
    */
   public class AdaptiveClassLoader12 extends AdaptiveClassLoader {
  -
  +    public static int debug=0;
  +    
       public AdaptiveClassLoader12()
       {
   	super();
  @@ -79,12 +80,19 @@
   	return cl;
       }
   
  +    void log( String s ) {
  +	System.out.println("AdaptiveClassLoader12: "  + s );
  +    }
  +    
       protected Class doDefineClass(String name, byte classData[], Object pd )
       {
   	//	System.out.println("XXX defineClass12 " + pd );
   	// 	if( sm != null ) {
  -	return defineClass(name, classData, 0, classData.length,
  -			   (ProtectionDomain)pd);
  +	if( debug > 0) log( name + " " +
  +			    ((ProtectionDomain)pd).getCodeSource() );
  +	Class c=defineClass(name, classData, 0, classData.length,
  +			    (ProtectionDomain)pd);
  +	return c;
   	// } else {
   	// 	    return  defineClass(name, classData, 0, classData.length);
   	// 	}
  
  
  
  1.8       +3 -1      jakarta-tomcat/src/share/org/apache/tomcat/loader/AdaptiveServletLoader.java
  
  Index: AdaptiveServletLoader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/loader/AdaptiveServletLoader.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- AdaptiveServletLoader.java	2000/06/15 00:26:47	1.7
  +++ AdaptiveServletLoader.java	2000/06/19 21:53:14	1.8
  @@ -143,7 +143,9 @@
       /** Return a real class loader
        */
       public ClassLoader getClassLoader() {
  -	if( classL==null && jdk12 ) {
  +	if( classL!=null)
  +	    return classL;
  +	if( jdk12 ) {
   	    try {
   		Class ld=Class.forName("org.apache.tomcat.loader.AdaptiveClassLoader12");
   		classL=(AdaptiveClassLoader)ld.newInstance();
  
  
  
  1.8       +217 -32   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.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- AccessInterceptor.java	2000/06/16 21:03:33	1.7
  +++ AccessInterceptor.java	2000/06/19 21:53:15	1.8
  @@ -83,7 +83,7 @@
    *  concepts - I think we can do that, but need to experiment with that)
    */
   public class AccessInterceptor extends  BaseInterceptor  {
  -    int debug=20;
  +    int debug=0;
       ContextManager cm;
   
       // Security mapping note
  @@ -98,7 +98,8 @@
   
       /* -------------------- Support functions -------------------- */
       public void setDebug( int i ) {
  -	System.out.println("setDebug " + i );
  +	if( debug > 0 || i>0)
  +	    System.out.println("setDebug " + i );
       }
       
       void log( String msg ) {
  @@ -137,42 +138,79 @@
       public void contextInit( Context ctx)
   	throws TomcatException
       {
  -	// Set default session manager if none set
  -	ServletWrapper authWrapper=new ServletWrapper();
  -	authWrapper.setContext( ctx );
  -	authWrapper.setServletName( "tomcat.authServlet");
   	String login_type=ctx.getAuthMethod();
  +	if( debug > 0 ) log( "Init  " + ctx.getHost() + " " +
  +			     ctx.getPath() + " " + login_type );
  +	
   	if( "FORM".equals( login_type )) {
  -	    authWrapper.setServletClass( "org.apache.tomcat.servlets.FormLoginServlet" );
  +	    String page=ctx.getFormLoginPage();
  +	    String errorPage = ctx.getFormErrorPage();
  +	    
  +	    if(page==null || errorPage==null) {
  +		ctx.log( "Form login without form pages, defaulting to basic "
  +			 + page + " " + errorPage);
  +		ctx.addServlet( new BasicAuthHandler());
  +		ctx.addErrorPage( "401", "tomcat.basicAuthHandler");
  +		return;
  +	    }
  +
  +	    // Workaround for common error - no "/" at start of page
  +	    if( ! page.startsWith("/")) {
  +		ctx.log("FORM: login page doesn't start with / " + page );
  +		page="/" + page;
  +	    }
  +	    if( ! errorPage.startsWith("/")) {
  +		ctx.log("FORM: error page doesn't start with / " + errorPage );
  +		errorPage="/" + errorPage;
  +	    }
  +
  +	    String cpath=ctx.getPath();
  +	    
  +	    // Workaround for common error - ctx path included
  +	    if( ! page.startsWith( cpath ) )
  +		page= cpath + page;
  +	    else 
  +		ctx.log("FORM: WARNING, login page starts with context path " +
  +			page);
  +	    
  +
  +	    if( ! errorPage.startsWith( cpath ) )
  +		errorPage= cpath + errorPage;
  +	    else 
  +		ctx.log("FORM: WARNING, error page starts with context path " +
  +			errorPage);
  +
  +	    // Adjust login and error paths - avoid computations in handlers
  +	    ctx.setFormLoginPage( page );
  +	    ctx.setFormErrorPage( errorPage );
  +
  +	    ctx.addServlet( new FormAuthHandler() );
  +	    ctx.addServlet( new FormSecurityCheckHandler() );
  +	    ctx.addErrorPage( "401", "tomcat.formAuthHandler");
  +
  +	    // Add mapping for the POST handler
  +	    String pageP=page.substring( cpath.length());
  +	    int lastS=pageP.lastIndexOf( "/" );
  +	    String location="/j_security_check";
  +	    if( lastS > 0 ) {
  +		location=pageP.substring( 0, lastS) +
  +		    "/j_security_check";
  +	    }
  +	    ctx.addServletMapping( location,
  +				   "tomcat.formSecurityCheck");
  +	    if( debug > 0 )
  +		ctx.log( "Map " + location +
  +			 " to tomcat.formSecurityCheck for " +
  +			 page);
   	} else if( "BASIC".equals( login_type )) {
  -	    authWrapper.setServletClass( "org.apache.tomcat.servlets.BasicLoginServlet" );
  +	    ctx.addServlet( new BasicAuthHandler());
  +	    ctx.addErrorPage( "401", "tomcat.basicAuthHandler");
   	} else {
   	    // if unknown, leave the normal 404 error handler to deal
   	    // with unauthorized access.
   	}
  -
  -	if( debug > 0 ) log( "Init  " + ctx.getHost() + " " +
  -			     ctx.getPath() + " " + login_type );
  -	ctx.addServlet( authWrapper );
       }
       
  -    /** Called when a context is added.
  -     */
  -    public void addContext( ContextManager cm, Context ctx )
  -	throws TomcatException
  -    {
  -    }
  -
  -    /** Called when a context is removed from a CM - we must ask the mapper to
  -	remove all the maps related with this context
  -     */
  -    public void removeContext( ContextManager cm, Context ctx )
  -	throws TomcatException
  -    {
  -	// nothing - will go away with the ctx
  -    }
  -    
  -
       // XXX not implemented - will deal with that after everything else works.
       public void removeContainer( Container ct )
   	throws TomcatException
  @@ -190,6 +228,10 @@
   	    getNote( secMapNote );
   	if( ctxSecurityC==null)
   	    ctxCt.setNote( secMapNote, new SecurityConstraints() );
  +
  +	log( "addContainer() " + ctx.getHost() + " " +
  +	     ctx.getPath() + " " +
  +	     ct.getPath() );
   	
   	if( ct.getRoles()!=null || ct.getTransport()!=null ) {
   	    if( debug > 0 )
  @@ -222,12 +264,15 @@
   	    Container ct=ctxSec.securityPatterns[i];
   	    if( match( ct, path, method ) ) {
   		String roles[]=ct.getRoles();
  +		String methods[]=ct.getMethods();
   		String transport=ct.getTransport();
   		if( debug>0) {
   		    StringBuffer sb=new StringBuffer("ACCESS: matched ");
  -		    sb.append(ct.getPath()).append(" ").
  -			append(ct.getMethods()).append(" ").
  -			append(transport).append(" ");
  +		    sb.append(ct.getPath()).append(" ");
  +		    if(methods!=null)
  +			for( int j=0; j< methods.length; j++ )
  +			    sb.append(methods[j]).append(" ");
  +		    sb.append(transport).append(" ");
   		    if( roles!=null)
   			for( int j=0; j< roles.length; j++ )
   			    sb.append( roles[j]).append(" ");
  @@ -292,5 +337,145 @@
       public synchronized void addContainer(Container ct) {
   	securityPatterns[ patterns ]= ct;
   	patterns++;
  +    }
  +}
  +
  +class BasicAuthHandler extends ServletWrapper {
  +    
  +    BasicAuthHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.basicAuthHandler";
  +    }
  +
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	Context ctx=req.getContext();
  +	String realm=ctx.getRealmName();
  +	if(realm==null) realm="default";
  +
  +	res.setHeader( "WWW-Authenticate",
  +		       "Basic realm=\"" + realm + "\"");
  +    }
  +}
  +
  +/** 401 - access denied. Will check if we have an authenticated user
  +    or not.
  +    XXX If we have user/pass, but still no permission  - display
  +    error page.
  +*/
  +class FormAuthHandler extends ServletWrapper {
  +    int debug=1;
  +    
  +    FormAuthHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.formAuthHandler";
  +    }
  +
  +    void log( String s ) {
  +	context.log( "FormAuthHandler: " + s );
  +    }
  +
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	Context ctx=req.getContext();
  +
  +	HttpSession session=req.getSession( false );
  +	if( session == null ) {
  +	}
  +	
  +	String page=ctx.getFormLoginPage();
  +	String errorPage=ctx.getFormErrorPage();
  +	// assert errorPage!=null ( AccessInterceptor will check
  +	// that and enable form login only if everything is ok
  +
  +	session=req.getSession( true );
  +	String username=(String)session.getAttribute( "j_username" );
  +	if( username != null ) {
  +	    // 401 with existing j_username - that means wrong credentials.
  +	    // Next time we'll have a fresh start
  +	    session.removeAttribute( "j_username");
  +	    session.removeAttribute( "j_password");
  +	    req.setAttribute("javax.servlet.error.message",
  +			     errorPage );
  +	    contextM.handleStatus( req, res, 302 ); // redirect
  +	    return;
  +	}
  +
  +	session.setAttribute( "tomcat.auth.originalLocation",
  +			      req.getRequestURI());
  +	if( debug > 0 )
  +	    log("Redirect1: " + page  + " originalUri=" + req.getRequestURI());
  +
  +	req.setAttribute("javax.servlet.error.message",
  +			 page );
  +	contextM.handleStatus( req, res, 302 ); // redirect
  +	return; 
  +    }
  +}
  +
  +/** 
  +    j_security_check handler
  +
  +    This is called after the user POST the form login page.
  +*/
  +class FormSecurityCheckHandler extends ServletWrapper {
  +    int debug=1;
  +    
  +    FormSecurityCheckHandler() {
  +	initialized=true;
  +	internal=true;
  +	name="tomcat.formSecurityCheck";
  +    }
  +
  +    void log( String s ) {
  +	context.log( "FormSecurityCheck: " + s );
  +    }
  +
  +
  +    /** Will set the j_username and j_password attributes
  +	in the session, and redirect to the original
  +	location.
  +	No need to validate user/pass and display error page
  +	if wrong user/pass. Will be done by normal 401 handler,
  +	if user/pass are wrong.
  +    */
  +    public void doService(Request req, Response res)
  +	throws Exception
  +    {
  +	String username=req.getParameter( "j_username" );
  +	String password=req.getParameter( "j_password" );
  +
  +	Context ctx=req.getContext();
  +	String errorPage=ctx.getFormErrorPage();
  +	// assert errorPage!=null ( AccessInterceptor will check
  +	// that and enable form login only if everything is ok
  +	
  +	if( debug > 0 )
  +	    log( " user/pass= " + username + " " + password );
  +	    
  +	HttpSession session=req.getSession( false );
  +	if( session == null ) {
  +	    ctx.log("From login without a session ");
  +	    req.setAttribute("javax.servlet.error.message",
  +			     errorPage );
  +	    contextM.handleStatus( req, res, 302 ); // redirect
  +	    return;
  +	}
  +	session.setAttribute( "j_username", username );
  +	session.setAttribute( "j_password", password );
  +	    
  +	String origLocation=(String)session.
  +	    getAttribute( "tomcat.auth.originalLocation");
  +
  +	if( debug > 0)
  +	    log("Redirect2: " + origLocation);
  +	
  +	req.setAttribute("javax.servlet.error.message",
  +			 origLocation );
  +	contextM.handleStatus( req, res, 302 ); // redirect
       }
   }
  
  
  
  1.2       +5 -3      jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleRealm.java
  
  Index: SimpleRealm.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleRealm.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SimpleRealm.java	2000/05/09 17:56:34	1.1
  +++ SimpleRealm.java	2000/06/19 21:53:15	1.2
  @@ -102,8 +102,9 @@
   	this.cm=cm;
   	// set-up a per/container note for maps
   	try {
  -	    // XXX make the name a "global" static - after everything is stable!
  -	    reqRolesNote = cm.getNoteId( ContextManager.REQUEST_NOTE, "required.roles");
  +	    // XXX make the name a "global" static - 
  +	    reqRolesNote = cm.getNoteId( ContextManager.REQUEST_NOTE,
  +					 "required.roles");
   	} catch( TomcatException ex ) {
   	    ex.printStackTrace();
   	    throw new RuntimeException( "Invalid state ");
  @@ -147,7 +148,8 @@
   	String user=(String)cred.get("username");
   	String password=(String)cred.get("password");
   	String userRoles[]=null;
  -	if( debug > 0 ) log( "Controled access for " + user + " " + req + " " + req.getContainer() );
  +	if( debug > 0 ) log( "Controled access for " + user + " " +
  +			     req + " " + req.getContainer() );
   
   	if( memoryRealm.checkPassword( user, password ) ) {
   	    req.setRemoteUser( user );
  
  
  
  1.5       +3 -2      jakarta-tomcat/src/share/org/apache/tomcat/startup/EmbededTomcat.java
  
  Index: EmbededTomcat.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/startup/EmbededTomcat.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- EmbededTomcat.java	2000/06/16 17:08:55	1.4
  +++ EmbededTomcat.java	2000/06/19 21:53:15	1.5
  @@ -296,6 +296,7 @@
   
   	PolicyInterceptor polI=new PolicyInterceptor();
   	addContextInterceptor( polI );
  +	//	polI.setDebug(20);
   
   	LoaderInterceptor loadI=new LoaderInterceptor();
   	addContextInterceptor( loadI );
  @@ -326,14 +327,14 @@
   	// access control ( find if a resource have constraints )
   	AccessInterceptor accessI=new AccessInterceptor();
   	addRequestInterceptor( accessI );
  -	accessI.setDebug(20);
  +	//	accessI.setDebug(20);
   
   	// set context class loader
   	Jdk12Interceptor jdk12I=new Jdk12Interceptor();
   	addRequestInterceptor( jdk12I );
   
   	// xXXX
  -	addRequestInterceptor( new SimpleRealm());
  +	//	addRequestInterceptor( new SimpleRealm());
       }
       
   
  
  
  
  1.3       +4 -4      jakarta-tomcat/src/share/org/apache/tomcat/util/PrefixMapper.java
  
  Index: PrefixMapper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/PrefixMapper.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- PrefixMapper.java	2000/06/16 17:08:58	1.2
  +++ PrefixMapper.java	2000/06/19 21:53:16	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/PrefixMapper.java,v 1.2 2000/06/16 17:08:58 costin Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/06/16 17:08:58 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/PrefixMapper.java,v 1.3 2000/06/19 21:53:16 costin Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/06/19 21:53:16 $
    *
    * ====================================================================
    *
  @@ -122,7 +122,7 @@
        */
       public void removeAllMappings( String host, String path ) {
   	PrefixMapper vmap=this;
  -	if( host==null ) {
  +	if( host!=null ) {
   	    vmap=(PrefixMapper)vhostMaps.get(host);
   	}
   	
  
  
  

Mime
View raw message