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/01 08:37:40 UTC

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

costin      00/01/31 23:37:40

  Modified:    src/share/org/apache/tomcat/core
                        BufferedServletOutputStream.java
                        ContextManager.java HttpServletResponseFacade.java
                        IncludedResponse.java Request.java RequestImpl.java
                        RequestInterceptor.java Response.java
                        ResponseImpl.java
               src/share/org/apache/tomcat/request SessionInterceptor.java
                        SimpleMapper.java
               src/share/org/apache/tomcat/service
                        Ajp11ConnectionHandler.java
               src/share/org/apache/tomcat/service/connector
                        Ajp12ConnectionHandler.java ConnectorResponse.java
               src/share/org/apache/tomcat/service/http
                        HttpResponseAdapter.java
               src/share/org/apache/tomcat/servlets DefaultErrorPage.java
                        DefaultServlet.java
  Added:       src/share/org/apache/tomcat/request FixHeaders.java
  Log:
  Big changes in Response.java - removed all "extra" methods, removed most
  of the XXX code in ResponseImpl.
  
  Craig, please take a loog at Response, we should try to use few common
  interfaces between Catalina and main - most of the methods in response are
  needed (IMHO), and probably you'll need to add them when you'll be close
  to a working Catalina to support full 2.2 ( buffering, etc) and for connectors.
  
  As part of the changes, the fixHeaders() moved to an interceptor and will be
  customizable ( since Apache sets it's own Server and Date header) and "custom"
  code can add special headers. The "beforeBody" method is used to give
  interceptors the chance to alter headers/state before being sent to user,
  and will always  be called before the first write to the Writer.
  
  All error processing code is now in DefaultErrorPage servlet ( used to be
  in ResponseImpl and ResponseWrapper). It's still hardcoded, but it's easy to
  replace it ( to add better/different reporting styles).
  
  Also changed the names of RequestInterceptor methods to reflect what happens
  at each stage - still need to figure an efficient way to set interceptors only
  for a number of "stages". Still need to add authenticate() and authorize()
  methods ( similar with Apache, IIS, NSAPI )
  
  Revision  Changes    Path
  1.8       +3 -10     jakarta-tomcat/src/share/org/apache/tomcat/core/BufferedServletOutputStream.java
  
  Index: BufferedServletOutputStream.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/BufferedServletOutputStream.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- BufferedServletOutputStream.java	2000/01/15 23:30:19	1.7
  +++ BufferedServletOutputStream.java	2000/02/01 07:37:36	1.8
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/BufferedServletOutputStream.java,v 1.7 2000/01/15 23:30:19 costin Exp $
  - * $Revision: 1.7 $
  - * $Date: 2000/01/15 23:30:19 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/BufferedServletOutputStream.java,v 1.8 2000/02/01 07:37:36 costin Exp $
  + * $Revision: 1.8 $
  + * $Date: 2000/02/01 07:37:36 $
    *
    * ====================================================================
    * 
  @@ -121,13 +121,7 @@
   	resA.doWrite( buffer, pos, count);
       }
   
  -    protected void endResponse() throws IOException {
  -	resA.endResponse();
  -    }
  -
       protected void sendHeaders() throws IOException {
  - 	if(resA!=null)
  - 	    resA.writeHeaders();
   	if(resA!=null)
   	    resA.endHeaders();
       }
  @@ -259,7 +253,6 @@
   	reallyFlush();
   	closed = true;
   	//	out.close();
  -	endResponse();
       }
   
       public boolean isContentWritten() {
  
  
  
  1.30      +12 -10    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.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- ContextManager.java	2000/01/30 04:22:46	1.29
  +++ ContextManager.java	2000/02/01 07:37:36	1.30
  @@ -351,11 +351,6 @@
   		return;
   	    }
   
  -	    //    don't do headers if request protocol is http/0.9
  -	    if (rrequest.getProtocol() == null) {
  -		rresponse.setOmitHeaders(true);
  -	    }
  -
   	    // XXX Hardcoded - it will be changed in the next step.( costin )
   
   	    processRequest( rrequest );
  @@ -373,13 +368,13 @@
   	    // finish and clean up
   	    rresponse.finish();
   	    
  -	    // protocol notification
  -	    rresponse.endResponse();
  -	    
   	} catch (Exception e) {
  +	    if(e instanceof IOException && "Broken pipe".equals(e.getMessage()) ) {
  +	    }
   	    // XXX
   	    // this isn't what we want, we want to log the problem somehow
   	    System.out.println("HANDLER THREAD PROBLEM: " + e);
  +	    System.out.println("Request: " + rrequest);
   	    e.printStackTrace();
   	}
       }
  @@ -397,11 +392,11 @@
   	if(debug>2) log("");
   
   	for( int i=0; i< requestInterceptors.size(); i++ ) {
  -	    ((RequestInterceptor)requestInterceptors.elementAt(i)).handleRequestContextMap( req );
  +	    ((RequestInterceptor)requestInterceptors.elementAt(i)).contextMap( req );
   	}
   
   	for( int i=0; i< requestInterceptors.size(); i++ ) {
  -	    ((RequestInterceptor)requestInterceptors.elementAt(i)).handleRequest( req );
  +	    ((RequestInterceptor)requestInterceptors.elementAt(i)).requestMap( req );
   	}
   
   	if(debug>2) log("After processing: ");
  @@ -410,6 +405,13 @@
   	return 0;
       }
   
  +    int doBeforeBody( Request req, Response res ) {
  +	for( int i=0; i< requestInterceptors.size(); i++ ) {
  +	    ((RequestInterceptor)requestInterceptors.elementAt(i)).beforeBody( req, res );
  +	}
  +	return 0;
  +    }
  +    
       // -------------------- Sub-Request mechanism --------------------
   
       // comment from Apache http_request.c
  
  
  
  1.2       +10 -17    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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HttpServletResponseFacade.java	1999/10/09 00:30:06	1.1
  +++ HttpServletResponseFacade.java	2000/02/01 07:37:36	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v 1.1 1999/10/09 00:30:06 duncan Exp $
  - * $Revision: 1.1 $
  - * $Date: 1999/10/09 00:30:06 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v 1.2 2000/02/01 07:37:36 costin Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/02/01 07:37:36 $
    *
    * ====================================================================
    *
  @@ -151,7 +151,7 @@
       }
   
       public void sendError(int sc) throws IOException {
  -	response.sendError(sc);
  +	response.sendError(sc, "No detailed message");
       }
       
       public void sendError(int sc, String msg) throws IOException {
  @@ -159,18 +159,12 @@
       }
   
       public void sendRedirect(String location)
  -    throws IOException, IllegalArgumentException {
  +	throws IOException, IllegalArgumentException
  +    {
           if (location == null) {
               String msg = sm.getString("hsrf.redirect.iae");
  -
               throw new IllegalArgumentException(msg);
   	}
  -
  -        // XXX
  -	// we want to do a better check than this in the future,
  -	// but as this isn't used on every hit, we'll do it the
  -	// slow way for now
  -
           response.sendRedirect(location);
       }
       
  @@ -183,11 +177,11 @@
       }
   
       public void setDateHeader(String name, long date) {
  -	response.setDateHeader(name, date);
  +	response.setHeader(name, new HttpDate(date).toString());
       }
   
       public void addDateHeader(String name, long value) {
  -	response.addDateHeader(name, value);
  +	response.addHeader(name, new HttpDate(value).toString());
       }
       
       public void setHeader(String name, String value) {
  @@ -199,11 +193,11 @@
       }
       
       public void setIntHeader(String name, int value) {
  -	response.setIntHeader(name, value);
  +	response.setHeader(name, Integer.toString(value));
       }
   
       public void addIntHeader(String name, int value) {
  -        response.addIntHeader(name, value);
  +        response.addHeader(name, Integer.toString(value));
       }
       
       public void setStatus(int sc) {
  @@ -242,7 +236,6 @@
        *
        * @deprecated
        */
  -    
       public void setStatus(int sc, String msg) {
   	response.setStatus(sc);
       }    
  
  
  
  1.4       +12 -5     jakarta-tomcat/src/share/org/apache/tomcat/core/IncludedResponse.java
  
  Index: IncludedResponse.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/IncludedResponse.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IncludedResponse.java	2000/01/12 19:54:01	1.3
  +++ IncludedResponse.java	2000/02/01 07:37:36	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/IncludedResponse.java,v 1.3 2000/01/12 19:54:01 costin Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/01/12 19:54:01 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/IncludedResponse.java,v 1.4 2000/02/01 07:37:36 costin Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/02/01 07:37:36 $
    *
    * ====================================================================
    *
  @@ -91,8 +91,15 @@
       
       public void sendError(int sc, String msg) throws IOException {
   	//	/*XXX*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
  -        getRealResponse().sendBodyText("Included servlet error: " + sc +
  -                                       ": " + msg + "\r\n");
  +	String s="Included servlet error: " + sc + ": " + msg + "\r\n";
  +        Response response=getRealResponse();
  +	if( response.isUsingStream() ) {
  +	    ServletOutputStream out = response.getOutputStream();
  +	    out.print(s);
  +	} else {
  +	    PrintWriter out = response.getWriter();
  +	    out.print(s);
  +	}
       }
   
       public void sendRedirect(String location) throws IOException {
  
  
  
  1.23      +90 -86    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.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Request.java	2000/01/15 23:30:20	1.22
  +++ Request.java	2000/02/01 07:37:36	1.23
  @@ -73,73 +73,89 @@
    *
    */
   public interface Request  {
  -    // Required fields
   
  +    // -------------------- Basic Request properties --------------------
       public String getScheme() ;
   
       public String getMethod() ;
   
       public String getRequestURI() ;
   
  +    public void setRequestURI( String r ) ;
  +
       public String getQueryString() ;
   
       public String getProtocol() ;
   
  -    public String getHeader(String name) ;
  -
  -    public Enumeration getHeaderNames() ;
  -
  -    
  -    public ServletInputStream getInputStream() 	throws IOException;
  -
       public String getServerName() ;
   
  +    public void setServerName(String serverName) ;
  +    
       public int getServerPort() ;
           
       public String getRemoteAddr() ;
   
       public String getRemoteHost() ;
   
  -    // Hints - will be set by Interceptors if not set
  -    // by adapter
  -    public String getLookupPath() ;
  +    // -------------------- Headers -------------------- 
  +    public String getHeader(String name) ;
   
  -    public void setLookupPath( String l ) ;
  +    public Enumeration getHeaderNames() ;
  +    
  +    public MimeHeaders getMimeHeaders();
   
  -    public String getAuthType() ;
  +    public long getDateHeader(String name) ;
   
  +    public Enumeration getHeaders(String name) ;
   
  -    String getPathTranslated() ;
  +    public int getIntHeader(String name)  ;
   
  -    public String getPathInfo() ;
  +    //-------------------- "Computed" properties --------------------
  +    // ( directly derived from headers or request paths )
   
  -    String getRemoteUser() ;
  +    /** Return the cookies
  +     */
  +    public String[] getCookieHeaders();
   
  -    boolean isSecure() ;
  -	
  -    Principal getUserPrincipal() ;
  +    public Cookie[] getCookies() ;
   
  -    boolean isUserInRole(String role) ;
  +    public int getContentLength() ;
   
  -    public String getRequestedSessionId() ;
  +    public void setContentLength( int  len ) ;
   
  -    public void setRequestedSessionId(String reqSessionId) ;
  +    public String getContentType() ;
   
  -    public String getServletPath() ;
  +    public void setContentType( String type ) ;
   
  -    boolean isRequestedSessionIdFromCookie() ;
  +    public void setCharEncoding( String enc ) ;
   
  -    boolean isRequestedSessionIdFromURL() ;
  +    public String getCharacterEncoding() ;
   
  +    // -------------------- Mapping --------------------
  +    // Will be set by mappers
       
  -    public void updatePaths() ;//XXX - not to be used, use RD
  +    public String getContextPath();
   
  -    public void setContext(Context context) ;
  +    public String getServletName();
   
  -    public HttpSession getSession(boolean create) ;
  +    // Hints - will be set by Interceptors if not set
  +    // by adapter
  +    public String getLookupPath() ;
   
  -    boolean isRequestedSessionIdValid() ;
  +    public void setLookupPath( String l ) ;
  +
  +    String getPathTranslated() ;
   
  +    public String getPathInfo() ;
  +
  +    public void setPathInfo(String pathInfo) ;
  +    
  +    public void setServletPath(String servletPath) ;
  +
  +    public String getServletPath() ;
  +
  +    public void updatePaths() ;//XXX - not to be used, use RD
  +
       public String getResolvedServlet() ;
   
       public void setResolvedServlet(String rs ) ;
  @@ -158,60 +174,56 @@
   
       public void setResourceName( String m ) ;
   
  -    public void setRequestURI( String r ) ;
  +    // -------------------- Security --------------------
  +    // Will be set by security interceptors
  +    public String getAuthType() ;
   
  +    public void setAuthType(String authType) ;
   
  -    public void setParameters( Hashtable h ) ;
  +    String getRemoteUser() ;
   
  -    public Hashtable getParameters() ;
  +    boolean isSecure() ;
  +	
  +    Principal getUserPrincipal() ;
   
  -    public void setContentLength( int  len ) ;
  +    boolean isUserInRole(String role) ;
   
  -    public void setContentType( String type ) ;
   
  -    public void setCharEncoding( String enc ) ;
  +    // -------------------- Session --------------------
  +    // Will be set by session interceptors
  +    public String getRequestedSessionId() ;
   
  -    public void setAuthType(String authType) ;
  +    public void setRequestedSessionId(String reqSessionId) ;
   
  +    boolean isRequestedSessionIdFromCookie() ;
   
  -    public void setPathInfo(String pathInfo) ;
  +    boolean isRequestedSessionIdFromURL() ;
   
  -    /** Set query string - will be called by forward
  -     */
  -    public void setQueryString(String queryString) ;
  +    public void setSession(HttpSession serverSession) ;
   
  -    
  -    // -------------------- Computed fields - will be computed if not set
  -    // ( computed at invocation time ! )
  -    public Cookie[] getCookies() ;
  +    public HttpSession getSession(boolean create) ;
   
  -    public Context getContext() ;
  +    boolean isRequestedSessionIdValid() ;
   
  -    public String[] getParameterValues(String name) ;
  +    // -------------------- Parameters --------------------
  +    // Derived from parsing query string and body (for POST)
   
  -    public Enumeration getParameterNames() ;
  +    public void setParameters( Hashtable h ) ;
   
  -    Hashtable getParametersCopy() ;
  +    public Hashtable getParameters() ;
   
  -    public String getCharacterEncoding() ;
  +    /** Set query string - will be called by forward
  +     */
  +    public void setQueryString(String queryString) ;
   
  -    public int getContentLength() ;
  +    public String[] getParameterValues(String name) ;
   
  -    public String getContentType() ;
  -    
  -    public HttpServletRequestFacade getFacade() ;
  +    public Enumeration getParameterNames() ;
   
  -    public void setResponse(Response response) ;
  +    Hashtable getParametersCopy() ;
   
  -    public Response getResponse() ;
  -    public RequestDispatcher getRequestDispatcher(String path);
       
  -    // -------------------- LookupResult 
  -    public void setSession(HttpSession serverSession) ;
  -    public void setServletPath(String servletPath) ;
  -
  -    public void setServerName(String serverName) ;
  -
  +    // -------------------- Attributes --------------------
       public Object getAttribute(String name) ;
       public void setAttribute(String name, Object value) ;
   
  @@ -219,32 +231,10 @@
   
       public Enumeration getAttributeNames() ;
   
  -    // -------------------- Facade for MimeHeaders
  -    public long getDateHeader(String name) ;
  -
  -    public Enumeration getHeaders(String name) ;
  -
  -    public int getIntHeader(String name)  ;
  -
  -    // -------------------- Utils - facade for RequestUtil
  +    // -------------------- Input --------------------
       public BufferedReader getReader() 	throws IOException;
  -
   
  -    // -------------------- End utils
  -    public void recycle() ;
  -
  -    public MimeHeaders getMimeHeaders();
  -
  -    /** Return the cookies
  -     */
  -    public String[] getCookieHeaders();
  -
  -    // server may have it pre-calculated - return null if
  -    // it doesn't
  -    public String getContextPath();
  -
  -    // Servlet name ( a smart server may use aliases and rewriting !!! )
  -    public String getServletName();
  +    public ServletInputStream getInputStream() 	throws IOException;
   
       /** Fill in the buffer. This method is probably easier to implement than
   	previous.
  @@ -259,5 +249,19 @@
       public int doRead() throws IOException;
       
   
  +    // -------------------- Internal methods --------------------
  +    public void recycle() ;
  +
  +    public Response getResponse() ;
  +
  +    public void setContext(Context context) ;
  +
  +    public HttpServletRequestFacade getFacade() ;
  +
  +    public void setResponse(Response response) ;
  +
  +    public Context getContext() ;
  +
  +    public RequestDispatcher getRequestDispatcher(String path);
   
   }
  
  
  
  1.10      +11 -5     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.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- RequestImpl.java	2000/01/29 05:51:31	1.9
  +++ RequestImpl.java	2000/02/01 07:37:36	1.10
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.9 2000/01/29 05:51:31 costin Exp $
  - * $Revision: 1.9 $
  - * $Date: 2000/01/29 05:51:31 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.10 2000/02/01 07:37:36 costin Exp $
  + * $Revision: 1.10 $
  + * $Date: 2000/02/01 07:37:36 $
    *
    * ====================================================================
    *
  @@ -141,8 +141,8 @@
       protected String remoteHost;
   
   
  -    protected StringManager sm =
  -        StringManager.getManager(Constants.Package);
  +    protected static StringManager sm =
  +        StringManager.getManager("org.apache.tomcat.core");
   
       public RequestImpl() {
    	headers = new MimeHeaders();
  @@ -746,5 +746,11 @@
   	sb.append( ",MP:" + getMappedPath() );
   	sb.append( "," + getWrapper() +") ");
   	return sb.toString();
  +    }
  +
  +
  +    // utility method - should be in a different class
  +    public static String getMessage( int status ) {
  +	return sm.getString("sc."+ status);
       }
   }
  
  
  
  1.3       +11 -8     jakarta-tomcat/src/share/org/apache/tomcat/core/RequestInterceptor.java
  
  Index: RequestInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestInterceptor.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RequestInterceptor.java	2000/01/30 04:22:46	1.2
  +++ RequestInterceptor.java	2000/02/01 07:37:36	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestInterceptor.java,v 1.2 2000/01/30 04:22:46 costin Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/01/30 04:22:46 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestInterceptor.java,v 1.3 2000/02/01 07:37:36 costin Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/02/01 07:37:36 $
    *
    * ====================================================================
    *
  @@ -75,14 +75,18 @@
       
       /** Will detect the context path for a request
        */
  -    //    public int contextMap(Request request);
  -    // XXX name will change!
  -    public int handleRequestContextMap(Request request);
  +    public int contextMap(Request request);
   
       /** Handle mapping inside a context
        */
  -    //    public int requestMap(Request request);
  +    public int requestMap(Request request);
   
  +    /** Called before the first body write, and before sending
  +     *  the headers. The interceptor have a chance to change the
  +     *  output headers.
  +     */
  +    public int beforeBody( Request request, Response response);
  +    
       /** Security
        */
       //    public int authentication(Request request);
  @@ -99,5 +103,4 @@
   
       //    public int log(Request request);
   
  -    public int handleRequest( Request request);
   }
  
  
  
  1.12      +56 -66    jakarta-tomcat/src/share/org/apache/tomcat/core/Response.java
  
  Index: Response.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Response.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- Response.java	2000/01/15 23:30:20	1.11
  +++ Response.java	2000/02/01 07:37:36	1.12
  @@ -77,117 +77,107 @@
    * @author costin@dnt.ro
    */
   public interface Response {
  -
  -    public HttpServletResponseFacade getFacade() ;
  -
  -    public void setRequest(Request request) ;
  -
  -    public boolean isStarted() ;
  -
  -    public boolean isCommitted() ;
  +    // -------------------- Headers -------------------- 
  +    public boolean containsHeader(String name) ;
   
  -    public String getServerHeader() ;
  +    public void setHeader(String name, String value) ;
   
  -    public void setServerHeader(String serverHeader) ;
  +    public void addHeader(String name, String value) ;
   
  -    public void setOmitHeaders(boolean omitHeaders) ;
  +    /** Signal that we're done with the headers, and body will follow.
  +     *  Any implementation needs to notify ContextManager, to allow
  +     *  interceptors to fix headers.
  +     */
  +    public void endHeaders() throws IOException;
   
  -    public void recycle() ;
  +    // -------------------- Output method --------------------
  +    /** True if getOutputStream or getWriter was called.
  +     *  XXX change it to "if any output was writen"
  +     *
  +     *  Used by RD.forward() and ServletWrapper.error()
  +     */
  +    public boolean isStarted() ;
   
  +    /** True if getOutputStream was called.
  +     *  Used to avoid the ugly try getWriter() catch getOutputStream.
  +     */
  +    public boolean isUsingStream();
  +    
  +    /** Signal that we're done with a particular request, the
  +	server can go on and read more requests or close the socket
  +    */
       public void finish() throws IOException ;
  -
  -    public boolean containsHeader(String name) ;
  -
   
  +    /** Either re-implement getOutputStream or return BufferedServletOutputStream(this)
  +	and implement doWrite();
  +     */
       public ServletOutputStream getOutputStream() ;
   
       public PrintWriter getWriter() throws IOException ;
  -
  -    public void setDateHeader(String name, long date) ;
  -
  -    public void addDateHeader(String name, long date) ;
   
  -    public void setHeader(String name, String value) ;
  -
  -
  -    public void addHeader(String name, String value) ;
  -
  -
  -    public void setIntHeader(String name, int value) ;
  -
  -    public void addIntHeader(String name, int value) ;
  +    /** Write a chunk of bytes. Should be called only from ServletOutputStream implementations,
  +     *	No need to implement it if your adapter implements ServletOutputStream.
  +     *  Headers and status will be written before this method is exceuted.
  +     */
  +    public void doWrite( byte buffer[], int pos, int count) throws IOException ;
   
  +    // -------------------- Buffering --------------------
  +    
       public int getBufferSize() ;
   
       public void setBufferSize(int size) throws IllegalStateException ;
   
  -    /*
  -     * Methodname "isCommitted" already taken by Response class.
  -     */
       public boolean isBufferCommitted() ;
   
       public void reset() throws IllegalStateException ;
   
       public void flushBuffer() throws IOException ;
   
  +    // -------------------- Cookies --------------------
   
  -    /** Set server-specific headers */
  -    void fixHeaders() throws IOException ;
  -
  -    /** Signal that we're done with a particular request, the
  -	server can go on and read more requests or close the socket
  -    */
  -    public void endResponse() throws IOException ;
  -
  -    // XXX should be abstract
  -    public void writeHeaders() throws IOException ;
  -
       public void addCookie(Cookie cookie) ;
   
       public void addSystemCookie(Cookie cookie) ;
   
  +    public Enumeration getCookies();
  +
  +    public Enumeration getSystemCookies();
  +
  +    // -------------------- Response properties --------------------
       public Locale getLocale() ;
   
       public void setLocale(Locale locale) ;
   
  -    String constructLocalizedContentType(String type, Locale loc) ;
  -
  +    /**  translate locale into encoding. 
  +     */
       public String getCharacterEncoding() ;
   
       public void setContentType(String contentType) ;
   
  -    public void setContentLength(int contentLength) ;
  +    public String getContentType();
   
  -    public int getStatus() ;
  +    public void setContentLength(int contentLength) ;
   
  -    public void setStatus(int status) ;
  +    public int getContentLength() ;
   
  -    public void sendError(int sc) throws IOException ;
  +    public void setStatus(int status);
   
  +    public int getStatus() ;
  +    
  +    // -------------------- Error --------------------
  +    // XXX, not needed, can be in Facade!!
       public void sendError(int sc, String msg) throws IOException ;
   
       public void sendRedirect(String location) throws IOException ;
  -
  -
  -    public void sendBodyText(String s) throws IOException ;
   
  +    // -------------------- Internal methods --------------------
  +    public HttpServletResponseFacade getFacade() ;
   
  -    public void addMimeHeaders(MimeHeaders headers) throws IOException;
  +    public void setRequest(Request request) ;
  +    
  +    public Request getRequest() ;
   
  -    /** Signal that we're done with the headers, and body will follow.
  -	The adapter doesn't have to maintain state, it's done inside the engine
  -    */
  -    public void endHeaders() throws IOException;
  +    public void recycle() ;
   
  -    /** Either implement ServletOutputStream or return BufferedServletOutputStream(this)
  -	and implement doWrite();
  -     */
  -    public ServletOutputStream getServletOutputStream() throws IOException;
  -    
  -    /** Write a chunk of bytes. Should be called only from ServletOutputStream implementations,
  -     *	No need to implement it if your adapter implements ServletOutputStream.
  -     *  Headers and status will be written before this method is exceuted.
  -     */
  -    public void doWrite( byte buffer[], int pos, int count) throws IOException ;
   
   }
  
  
  
  1.10      +96 -325   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.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ResponseImpl.java	2000/01/29 05:51:32	1.9
  +++ ResponseImpl.java	2000/02/01 07:37:36	1.10
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v 1.9 2000/01/29 05:51:32 costin Exp $
  - * $Revision: 1.9 $
  - * $Date: 2000/01/29 05:51:32 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v 1.10 2000/02/01 07:37:36 costin Exp $
  + * $Revision: 1.10 $
  + * $Date: 2000/02/01 07:37:36 $
    *
    * ====================================================================
    *
  @@ -79,8 +79,8 @@
    * @author Hans Bergsten <ha...@gefionsoftware.com>
    */
   public class ResponseImpl implements Response {
  -    protected StringManager sm =
  -        StringManager.getManager(Constants.Package);
  +    protected static StringManager sm =
  +        StringManager.getManager("org.apache.tomcat.core");
   
       protected Request request;
       protected HttpServletResponseFacade responseFacade;
  @@ -101,11 +101,7 @@
       protected boolean usingWriter = false;
       protected boolean started = false;
       protected boolean committed = false;
  -    protected boolean omitHeaders = false;
  -    protected String serverHeader = null;
   
  -    String message;
  -    BufferedServletOutputStream sos=new BufferedServletOutputStream(this);
       StringBuffer body=new StringBuffer();
   
       public ResponseImpl() {
  @@ -122,24 +118,14 @@
   	this.request = request;
       }
   
  -    public boolean isStarted() {
  -	return started;
  +    public Request getRequest() {
  +	return request;
       }
   
  -    public boolean isCommitted() {
  -	return committed;
  -    }
  -
  -    public String getServerHeader() {
  -        return serverHeader;
  -    }
  -
  -    public void setServerHeader(String serverHeader) {
  -        this.serverHeader = serverHeader;
  -    }
  -
  -    public void setOmitHeaders(boolean omitHeaders) {
  -	this.omitHeaders = omitHeaders;
  +    /* -------------------- */
  +    
  +    public boolean isStarted() {
  +	return started;
       }
   
       public void recycle() {
  @@ -157,13 +143,9 @@
   	out.recycle();
   	started = false;
   	committed = false;
  -	omitHeaders=false;
   
   	// adapter
  -	sos.recycle();
  -	headers.clear();
   	status=-1;
  -	message=null;
   	body.setLength(0);
       }
   
  @@ -171,8 +153,10 @@
   	try {
   	    if (usingWriter && (writer != null)) {
   	        writer.flush();
  +		writer.close();
   	    }
   	    out.reallyFlush();
  +	    out.close();
   	} catch (SocketException e) {
   	    return;  // munch
   	} catch (IOException e) {
  @@ -189,67 +173,47 @@
       // XXX
       // mark whether or not we are being used as a stream our writer
   
  -    public ServletOutputStream getOutputStream() {
  -	started = true;
  -
  -	if (usingWriter) {
  -	    String msg = sm.getString("serverResponse.outputStream.ise");
  -
  -	    throw new IllegalStateException(msg);
  -	}
  -
  -	usingStream = true;
  -
  -	return out;
  +    public boolean isUsingStream() {
  +	return usingStream;
       }
  -
  +    
       public PrintWriter getWriter() throws IOException {
  -	started = true;
  -
  +	if(writer!=null) return writer;
  +	// it already did all the checkings
  +	
   	if (usingStream) {
   	    String msg = sm.getString("serverResponse.writer.ise");
  -
   	    throw new IllegalStateException(msg);
   	}
   
  +	started = true;
   	usingWriter = true;
  -
  -	if (writer == null) {
  -	    String encoding = getCharacterEncoding();
   
  -            // XXX - EBCDIC issue here?
  +	String encoding = getCharacterEncoding();
   
  -	    if ((encoding == null) || "Default".equals(encoding) )
  -	        writer = new PrintWriter(new OutputStreamWriter(out));
  -	    else
  -		try {
  -		    writer = new PrintWriter(new OutputStreamWriter(out, encoding));
  -		} catch (java.io.UnsupportedEncodingException ex) {
  -		    // if we don't do that, the runtime exception will propagate
  -		    // and we'll try to send an error page - but surprise, we
  -		    // still can't get the Writer to send the error page...
  -		    writer = new PrintWriter( new OutputStreamWriter(out));
  -
  -		    // Deal with strange encodings - webmaster should see a message
  -		    // and install encoding classes - n new, unknown language was discovered,
  -		    // and they read our site!
  -		    System.out.println("Unsuported encoding: " + encoding );
  -		}
  -	}
  +	// XXX - EBCDIC issue here?
   
  -	out.setUsingWriter (usingWriter);
  +	if ((encoding == null) || "Default".equals(encoding) )
  +	    writer = new PrintWriter(new OutputStreamWriter(out));
  +	else
  +	    try {
  +		writer = new PrintWriter(new OutputStreamWriter(out, encoding));
  +	    } catch (java.io.UnsupportedEncodingException ex) {
  +		// if we don't do that, the runtime exception will propagate
  +		// and we'll try to send an error page - but surprise, we
  +		// still can't get the Writer to send the error page...
  +		writer = new PrintWriter( new OutputStreamWriter(out));
  +		
  +		// Deal with strange encodings - webmaster should see a message
  +		// and install encoding classes - n new, unknown language was discovered,
  +		// and they read our site!
  +		System.out.println("Unsuported encoding: " + encoding );
  +	    }
  +	out.setUsingWriter (true);
   
   	return writer;
       }
   
  -    public void setDateHeader(String name, long date) {
  -	headers.putDateHeader(name, date);
  -    }
  -
  -    public void addDateHeader(String name, long date) {
  -        headers.addDateHeader(name, date);
  -    }
  -
       public void setHeader(String name, String value) {
   	headers.putHeader(name, value);
       }
  @@ -258,14 +222,6 @@
           headers.addHeader(name, value);
       }
   
  -    public void setIntHeader(String name, int value) {
  -	headers.putIntHeader(name, value);
  -    }
  -
  -    public void addIntHeader(String name, int value) {
  -        headers.addIntHeader(name, value);
  -    }
  -
       public int getBufferSize() {
   	return out.getBufferSize();
       }
  @@ -273,7 +229,7 @@
       public void setBufferSize(int size) throws IllegalStateException {
   
   	// Force the PrintWriter to flush the data to the OutputStream.
  -	if (usingWriter == true) writer.flush();
  +	if (usingWriter == true && writer != null ) writer.flush();
   
   	if (out.isContentWritten() == true) {
   	    String msg = sm.getString("servletOutputStreamImpl.setbuffer.ise");
  @@ -300,7 +256,7 @@
   	contentLength = -1;
   	status = 200;
   
  -	if (usingWriter == true)
  +	if (usingWriter == true && writer != null)
   	    writer.flush();
   
   	// Reset the stream
  @@ -313,88 +269,27 @@
       }
   
       public void flushBuffer() throws IOException {
  -	if (usingWriter == true)
  +	if (usingWriter == true && writer != null)
   	    writer.flush();
   
   	out.reallyFlush();
       }
   
   
  -    /** Set server-specific headers */
  -    public void fixHeaders() throws IOException {
  -	//	System.out.println( "Fixing headers" );
  -	HttpDate date = new HttpDate(System.currentTimeMillis());
  -	headers.putHeader("Date", date.toString());
  -
  -	headers.putIntHeader("Status", status);
  -        headers.putHeader("Content-Type", contentType);
  -
  -	// Generated by Server!!!
  -	//headers.putDateHeader("Date",System.currentTimeMillis());
  -	if( getServerHeader()!=null)
  -	    headers.putHeader("Server",getServerHeader());
  -	if (contentLanguage != null) {
  -            headers.putHeader("Content-Language",contentLanguage);
  -        }
  -
  -	// context is null if we are in a error handler before the context is
  -	// set ( i.e. 414, wrong request )
  -	if( request.getContext() != null)
  -	    headers.putHeader("Servlet-Engine", request.getContext().getEngineHeader());
  -
  -
  -        if (contentLength != -1) {
  -            headers.putIntHeader("Content-Length", contentLength);
  -        }
  -
  -        // write cookies
  -        Enumeration cookieEnum = null;
  -        cookieEnum = systemCookies.elements();
  -        while (cookieEnum.hasMoreElements()) {
  -            Cookie c  = (Cookie)cookieEnum.nextElement();
  -            addHeader( CookieTools.getCookieHeaderName(c),
  -			       CookieTools.getCookieHeaderValue(c));
  -	    if( c.getVersion() == 1 ) {
  -		// add a version 0 header too.
  -		// XXX what if the user set both headers??
  -		Cookie c0 = (Cookie)c.clone();
  -		c0.setVersion(0);
  -		addHeader( CookieTools.getCookieHeaderName(c0),
  -				   CookieTools.getCookieHeaderValue(c0));
  -	    }
  -        }
  -	// XXX duplicated code, ugly
  -        cookieEnum = userCookies.elements();
  -        while (cookieEnum.hasMoreElements()) {
  -            Cookie c  = (Cookie)cookieEnum.nextElement();
  -            addHeader( CookieTools.getCookieHeaderName(c),
  -			       CookieTools.getCookieHeaderValue(c));
  -	    if( c.getVersion() == 1 ) {
  -		// add a version 0 header too.
  -		// XXX what if the user set both headers??
  -		Cookie c0 = (Cookie)c.clone();
  -		c0.setVersion(0);
  -		addHeader( CookieTools.getCookieHeaderName(c0),
  -				   CookieTools.getCookieHeaderValue(c0));
  -	    }
  -        }
  -	// XXX
  -        // do something with content encoding here
  -    }
  -
  -    // XXX should be abstract
  -    public void endResponse() throws IOException {
  -	//	resA.endResponse();
  -    }
  -
  -    // XXX should be abstract
  -    public void writeHeaders() throws IOException {
  -	if(omitHeaders)
  +    /** Signal that we're done with the headers, and body will follow.
  +     *  Any implementation needs to notify ContextManager, to allow
  +     *  interceptors to fix headers.
  +     */
  +    public void endHeaders() throws IOException {
  +	if(request.getProtocol()==null) // HTTP/0.9 
   	    return;
  +
  +	// let CM notify interceptors and give a chance to fix
  +	// the headers
  +	if(request.getContext() != null) 
  +	    request.getContext().getContextManager().doBeforeBody(request, this);
   
  -	setStatus( status, sm.getString("sc."+ status ));
  -	fixHeaders();
  -	addMimeHeaders( headers );
  +	// No action.. 
       }
   
       public void addCookie(Cookie cookie) {
  @@ -434,7 +329,10 @@
           setContentType(newType);
       }
   
  -    public String constructLocalizedContentType(String type, Locale loc) {
  +    /** Utility method for parsing the mime type and setting
  +     *  the encoding to locale. Also, convert from java Locale to mime encodings
  +    */
  +    private static String constructLocalizedContentType(String type, Locale loc) {
           // Cut off everything after the semicolon
           int semi = type.indexOf(";");
           if (semi != -1) {
  @@ -462,193 +360,66 @@
           }
       }
   
  +    public String getContentType() {
  +	return contentType;
  +    }
  +    
       public void setContentLength(int contentLength) {
   	this.contentLength = contentLength;
       }
  -
  -    public int getStatus() {
  -        return status;
  -    }
   
  -    public void setStatus(int status) {
  -        this.status = status;
  +    public int getContentLength() {
  +	return contentLength;
       }
   
  -    public void sendError(int sc) throws IOException {
  -	//	System.out.println("Send error " + sc );
  -	/*XXX*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
  -	sendError(sc, "No detailed message");
  +    public int getStatus() {
  +        return status;
       }
   
       public void sendError(int sc, String msg) throws IOException {
  -	// 	System.out.println("Send error " + sc + " " + msg);
  -	// 	System.out.println("Original request " + request.getRequestURI());
  -	// 	System.out.println(request.getContext().getClassPath());
  -	//	/*XXX*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
   	this.status = sc;
  -
  -	Context context = request.getContext();
  -
  -	if (context == null) {
  -	    sendPrivateError(sc, msg);
  -
  -	    return;
  -	}
  -
  -	ServletContextFacade contextFacade = context.getFacade();
  -	String path = context.getErrorPage(String.valueOf(sc));
  -
  -	if (path != null) {
  -	    RequestDispatcher rd = contextFacade.getRequestDispatcher(path);
  -	    request.setAttribute("javax.servlet.error.status_code",
  -                String.valueOf(sc));
  -	    request.setAttribute("javax.servlet.error.message", msg);
  -
  -	    try {
  -		reset();
  -		rd.forward(request.getFacade(), this.getFacade());
  -	    } catch (IllegalStateException ise) {
  -		// too late for a forward
  -		try {
  -		    rd.include(request.getFacade(), this.getFacade());
  -		} catch (ServletException se) {
  -		    sendPrivateError(sc, msg);
  -		}
  -	    } catch (ServletException se) {
  -		sendPrivateError(sc, msg);
  -	    }
  -	} else {
  -	    sendPrivateError(sc, msg);
  -	}
  -
  -	// XXX
  -	// we only should set this if we are the head, not in an include
  -
  -	close();
  -    }
  -
  -    private void sendPrivateError(int sc, String msg) throws IOException {
  -	setContentType("text/html");
  -
  -	StringBuffer buf = new StringBuffer();
  -	buf.append("<h1>Error: " + sc + "</h1>\r\n");
  -	buf.append(msg + "\r\n");
  -
  -	// XXX
  -	// need to figure out if we are in an include better. The subclass
  -	// knows whether or not we are in an include!
  +	request.setAttribute("javax.servlet.error.status_code",
  +			     String.valueOf(sc));
  +	request.setAttribute("javax.servlet.error.message", msg);
   
  -	sendBodyText(buf.toString());
  -    }
  -
  -    public void sendRedirect(String location) throws IOException {
  -	setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
  -	//mimeType = null;
  -	setContentType(Constants.ContentType.HTML);	// ISO-8859-1 default
  -
  -        location = makeAbsolute(location);
  -
  -	setHeader("Location", location);
  -
  -	StringBuffer buf = new StringBuffer();
  -	buf.append("<head><title>Document moved</title></head>\r\n");
  -	buf.append("<body><h1>Document moved</h1>\r\n");
  -	buf.append("This document has moved <a href=\"");
  -	buf.append(location);
  -	buf.append("\">here</a>.<p>\r\n");
  -	buf.append("</body>\r\n");
  -
  -	String body = buf.toString();
  -
  -	setContentLength(body.length());
  -
  -	sendBodyText(body);
  -
  -	close();
  -    }
  -
  -    private String makeAbsolute(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(
  -                                request.getFacade()).toString();
  -	    try {
  -	        url = new URL(new URL(requrl), location);
  -	    }
  -	    catch (MalformedURLException ignored) {
  -	        // Give up
  -	        return location;
  -	    }
  -	}
  -        return url.toString();
  -    }
  -
  -    public void sendBodyText(String s) throws IOException {
  +	// XXX need to customize it
  +	Servlet errorP=new org.apache.tomcat.servlets.DefaultErrorPage();
   	try {
  -	    PrintWriter out = getWriter();
  -	    out.print(s);
  -	} catch (IllegalStateException ise) {
  -	    ServletOutputStream out = getOutputStream();
  -	    out.print(s);
  +	    errorP.service(request.getFacade(),getFacade());
  +	} catch (ServletException ex ) {
  +	    // shouldn't happen!
  +	    ex.printStackTrace();
   	}
       }
   
  -    private void close() throws IOException {
  -	try {
  -	    PrintWriter out = getWriter();
  -	    out.close();
  -	} catch (IOException err) {
  -	    if("Broken pipe".equals( err.getMessage()))
  -		System.out.println("Broken pipe");
  -	    else
  -		throw err;
  -	} catch (IllegalStateException ise) {
  -	    ServletOutputStream out = getOutputStream();
  -	    out.close();
  -	}
  +    public void sendRedirect(String location) throws IOException {
  +	sendError(HttpServletResponse.SC_MOVED_TEMPORARILY,
  +		  location);
       }
  -
  -
       
  -    /** Set the response status and message. 
  -     *	@param message null will set the "default" message, "" will send no message
  +    /** Set the response status 
        */ 
  -    public void setStatus( int status, String message) throws IOException {
  +    public void setStatus( int status ) {
   	this.status=status;
  -	this.message=message;
  -    }
  -
  -    // XXX This one or multiple addHeader?
  -    // Probably not a big deal - but an adapter may have
  -    // an optimized version for this one ( one round-trip only )
  -    public void addMimeHeaders(MimeHeaders headers) throws IOException {
  -	int size = headers.size();
  -        for (int i = 0; i < size; i++) {
  -            MimeHeaderField h = headers.getField(i);
  -            addHeader( h.getName(), h.getValue());
  -        }
  -    }
  -
  -    /** Signal that we're done with the headers, and body will follow.
  -	The adapter doesn't have to maintain state, it's done inside the engine
  -    */
  -    public void endHeaders() throws IOException {
  -
       }
   
       /** Either implement ServletOutputStream or return BufferedServletOutputStream(this)
   	and implement doWrite();
        */
  -    public ServletOutputStream getServletOutputStream() throws IOException {
  -	return sos;
  +    public ServletOutputStream getOutputStream() {
  +	started = true;
  +
  +	if (usingWriter) {
  +	    String msg = sm.getString("serverResponse.outputStream.ise");
  +	    throw new IllegalStateException(msg);
  +	}
  +
  +	usingStream = true;
  +
  +	return out;
       }
  -	
       
  +
       /** Write a chunk of bytes. Should be called only from ServletOutputStream implementations,
        *	No need to implement it if your adapter implements ServletOutputStream.
        *  Headers and status will be written before this method is exceuted.
  @@ -659,13 +430,13 @@
                       Constants.CharacterEncoding.Default) );
       }
   
  -    public String getMessage() {
  -	return message;
  -    }
  -
       public StringBuffer getBody() {
   	return body;
       }
   
  +    // utility method - should be in a different class
  +    public static String getMessage( int status ) {
  +	return sm.getString("sc."+ status);
  +    }
       
   }
  
  
  
  1.5       +6 -2      jakarta-tomcat/src/share/org/apache/tomcat/request/SessionInterceptor.java
  
  Index: SessionInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SessionInterceptor.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SessionInterceptor.java	2000/01/30 04:22:47	1.4
  +++ SessionInterceptor.java	2000/02/01 07:37:38	1.5
  @@ -82,7 +82,7 @@
       public SessionInterceptor() {
       }
   	
  -    public int handleRequest(Request request ) {
  +    public int requestMap(Request request ) {
   	// look for session id -- cookies only right now
   	String sessionId = null;
   
  @@ -111,7 +111,11 @@
   	return 0;
       }
   
  -    public int handleRequestContextMap( Request rrequest ) {
  +    public int contextMap( Request rrequest ) {
  +	return 0;
  +    }
  +
  +    public int beforeBody( Request rrequest, Response response ) {
   	return 0;
       }
   
  
  
  
  1.3       +5 -3      jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleMapper.java
  
  Index: SimpleMapper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleMapper.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SimpleMapper.java	2000/01/30 04:22:47	1.2
  +++ SimpleMapper.java	2000/02/01 07:37:38	1.3
  @@ -94,7 +94,7 @@
       /** First step of request porcessing is finding the Context.
        *  Advanced mappers will do only one parsing.
        */
  -    public int handleRequestContextMap( Request rrequest ) {
  +    public int contextMap( Request rrequest ) {
   	// someone else set it up, no need to worry
   	if( rrequest.getContext() != null )
   	    return OK;
  @@ -116,7 +116,7 @@
       }
   
   
  -    public int handleRequest(Request req) {
  +    public int requestMap(Request req) {
   	Context context=req.getContext();
   	String path=req.getLookupPath();
           ServletWrapper wrapper = null;
  @@ -152,7 +152,9 @@
   	return OK;
       }
   
  -
  +    public int beforeBody( Request request, Response response) {
  +	return 0;
  +    }
   
       /** Get an exact match ( /catalog ) - rule 1 in 10.1
        */
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/request/FixHeaders.java
  
  Index: FixHeaders.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.request;
  
  import org.apache.tomcat.core.*;
  import org.apache.tomcat.util.*;
  import org.apache.tomcat.deployment.*;
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.servlet.http.*;
  
  /**
   *  Will generate the output headers ( cookies, etc ) plus tomcat-specific headers.
   * 
   */
  public class FixHeaders implements RequestInterceptor {
      
      public FixHeaders() {
      }
  	
      public int requestMap(Request request ) {
  	return 0;
      }
  
      public int contextMap( Request rrequest ) {
  	return 0;
      }
  
      public int beforeBody( Request request, Response response ) {
  	HttpDate date = new HttpDate(System.currentTimeMillis());
  	response.setHeader("Date", date.toString());
  	response.setHeader("Status", Integer.toString(response.getStatus()));
          response.setHeader("Content-Type", response.getContentType());
  
  	String contentLanguage=response.getLocale().getLanguage();
  	if (contentLanguage != null) {
              response.setHeader("Content-Language",contentLanguage);
          }
  
  	// context is null if we are in a error handler before the context is
  	// set ( i.e. 414, wrong request )
  	if( request.getContext() != null)
  	    response.setHeader("Servlet-Engine", request.getContext().getEngineHeader());
  
  
  	int contentLength=response.getContentLength();
          if (contentLength != -1) {
              response.setHeader("Content-Length", Integer.toString(contentLength));
          }
  
          // write cookies
          Enumeration cookieEnum = null;
          cookieEnum = response.getSystemCookies();
          while (cookieEnum.hasMoreElements()) {
              Cookie c  = (Cookie)cookieEnum.nextElement();
              response.addHeader( CookieTools.getCookieHeaderName(c),
  			       CookieTools.getCookieHeaderValue(c));
  	    if( c.getVersion() == 1 ) {
  		// add a version 0 header too.
  		// XXX what if the user set both headers??
  		Cookie c0 = (Cookie)c.clone();
  		c0.setVersion(0);
  		response.addHeader( CookieTools.getCookieHeaderName(c0),
  				    CookieTools.getCookieHeaderValue(c0));
  	    }
          }
  	
  	// XXX duplicated code, ugly
          cookieEnum = response.getCookies();
          while (cookieEnum.hasMoreElements()) {
              Cookie c  = (Cookie)cookieEnum.nextElement();
              response.addHeader( CookieTools.getCookieHeaderName(c),
  		       CookieTools.getCookieHeaderValue(c));
  	    if( c.getVersion() == 1 ) {
  		// add a version 0 header too.
  		// XXX what if the user set both headers??
  		Cookie c0 = (Cookie)c.clone();
  		c0.setVersion(0);
  		response.addHeader( CookieTools.getCookieHeaderName(c0),
  				   CookieTools.getCookieHeaderValue(c0));
  	    }
          }
  	return 0;
      }
  
  }
  
  
  
  1.13      +4 -4      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.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Ajp11ConnectionHandler.java	2000/01/15 23:30:23	1.12
  +++ Ajp11ConnectionHandler.java	2000/02/01 07:37:38	1.13
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.12 2000/01/15 23:30:23 costin Exp $
  - * $Revision: 1.12 $
  - * $Date: 2000/01/15 23:30:23 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.13 2000/02/01 07:37:38 costin Exp $
  + * $Revision: 1.13 $
  + * $Date: 2000/02/01 07:37:38 $
    *
    * ====================================================================
    *
  @@ -314,7 +314,7 @@
   class Ajp11ResponseAdapter extends HttpResponseAdapter {
       /** Override setStatus
        */
  -    public void setStatus( int status, String message) throws IOException {
  +    public void sendStatus( int status, String message) throws IOException {
   	statusSB.setLength(0);
   	statusSB.append("Status: " ).append( status ).append("\r\n");
   	sout.write(statusSB.toString().getBytes());
  
  
  
  1.9       +1 -1      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.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Ajp12ConnectionHandler.java	2000/01/15 23:30:24	1.8
  +++ Ajp12ConnectionHandler.java	2000/02/01 07:37:38	1.9
  @@ -321,7 +321,7 @@
   class AJP12ResponseAdapter extends HttpResponseAdapter {
       /** Override setStatus
        */
  -    public void setStatus( int status, String message) throws IOException {
  +    protected void sendStatus( int status, String message)  throws IOException {
   	statusSB.setLength(0);
   	statusSB.append("Status: " ).append( status ).append("\r\n");
   	sout.write(statusSB.toString().getBytes());
  
  
  
  1.4       +9 -8      jakarta-tomcat/src/share/org/apache/tomcat/service/connector/ConnectorResponse.java
  
  Index: ConnectorResponse.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/ConnectorResponse.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ConnectorResponse.java	2000/01/13 18:20:35	1.3
  +++ ConnectorResponse.java	2000/02/01 07:37:39	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/ConnectorResponse.java,v 1.3 2000/01/13 18:20:35 costin Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/01/13 18:20:35 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/ConnectorResponse.java,v 1.4 2000/02/01 07:37:39 costin Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/02/01 07:37:39 $
    *
    * ====================================================================
    *
  @@ -100,12 +100,12 @@
       }
   
       // XXX if more headers that MAX_SIZE, send 2 packets!   
  -    public void writeHeaders() throws IOException {
  -	//	System.out.println("Writing headers");
  -        if (omitHeaders) {
  +    public void endHeaders() throws IOException {
  +	super.endHeaders();
  +	
  +        if (request.getProtocol() == null) {
               return;
           }
  -	fixHeaders();
   	
   	MsgBuffer msg=con.getMsgBuffer();
   	msg.reset();
  @@ -125,7 +125,8 @@
        }
   
   
  -    public void endResponse() throws IOException {
  +    public void finish() throws IOException {
  +	super.finish();
   	MsgBuffer msg=con.getMsgBuffer();
   	msg.reset();
   	msg.appendInt( END_RESPONSE );
  
  
  
  1.5       +30 -38    jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java
  
  Index: HttpResponseAdapter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- HttpResponseAdapter.java	2000/01/15 23:30:26	1.4
  +++ HttpResponseAdapter.java	2000/02/01 07:37:39	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v 1.4 2000/01/15 23:30:26 costin Exp $
  - * $Revision: 1.4 $
  - * $Date: 2000/01/15 23:30:26 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v 1.5 2000/02/01 07:37:39 costin Exp $
  + * $Revision: 1.5 $
  + * $Date: 2000/02/01 07:37:39 $
    *
    * ====================================================================
    *
  @@ -99,52 +99,44 @@
   	headersSB.setLength(0);
       }
   
  -    public void setStatus( int status, String message ) throws IOException {
  -	// statusSB.reset();
  -	statusSB.append("HTTP/1.0 ").append(status);
  -	if(message!=null) statusSB.append(" ").append(message);
  -	statusSB.append("\r\n");
  -	sout.write(statusSB.toString().getBytes(Constants.CharacterEncoding.Default));
  -	statusSB.setLength(0);
  -    }
  -    
       public void setOutputStream(OutputStream os) {
   	sout = os;
       }
   
  -    public void addHeader(String name, String value) { //throws IOException{
  -	headersSB.setLength(0);
  -	headersSB.append(name).append(": ").append(value).append("\r\n");
  -	try {
  -	    sout.write( headersSB.toString().getBytes(Constants.CharacterEncoding.Default) );
  -	} catch( IOException ex ) {
  -	    ex.printStackTrace();
  -	    //XXX mark the error - should abandon everything 
  -	}
  -    }
  -    
  -    public void addMimeHeaders(MimeHeaders headers) throws IOException {
  -	headersSB.setLength(0);
  -	int size = headers.size();
  -        for (int i = 0; i < size; i++) {
  -            MimeHeaderField h = headers.getField(i);
  -            headersSB.append(h).append("\r\n");
  -        }
  -	sout.write( headersSB.toString().getBytes(Constants.CharacterEncoding.Default) );
  -    }
  -
       static final byte CRLF[]= { (byte)'\r', (byte)'\n' };
       
       public void endHeaders()  throws IOException {
  +	super.endHeaders();
  +	
  +	sendStatus( status, ResponseImpl.getMessage( status ));
  +
  +	Enumeration e = headers.names();
  +	while (e.hasMoreElements()) {
  +	    String name = (String)e.nextElement();
  +	    String value = headers.getHeader(name);
  +	    headersSB.setLength(0);
  +	    headersSB.append(name).append(": ").append(value).append("\r\n");
  +	    try {
  +		sout.write( headersSB.toString().getBytes(Constants.CharacterEncoding.Default) );
  +	    } catch( IOException ex ) {
  +		ex.printStackTrace();
  +		//XXX mark the error - should abandon everything 
  +	    }
  +	}
   	sout.write( CRLF, 0, 2 );
  -    }
  -
  -    public void endResponse() throws IOException {
   	sout.flush();
       }
   
  -    public ServletOutputStream getServletOutputStream() throws IOException {
  -	return null; // use default
  +    /** Needed for AJP  support - the only difference between AJP response and
  +	HTTP response is the status line
  +    */
  +    protected void sendStatus( int status, String message ) throws IOException {
  +	// statusSB.reset();
  +	statusSB.append("HTTP/1.0 ").append(status);
  +	if(message!=null) statusSB.append(" ").append(message);
  +	statusSB.append("\r\n");
  +	sout.write(statusSB.toString().getBytes(Constants.CharacterEncoding.Default));
  +	statusSB.setLength(0);
       }
   
       public void doWrite( byte buffer[], int pos, int count) throws IOException {
  
  
  
  1.2       +130 -7    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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- DefaultErrorPage.java	2000/01/14 04:08:11	1.1
  +++ DefaultErrorPage.java	2000/02/01 07:37:40	1.2
  @@ -59,6 +59,7 @@
   package org.apache.tomcat.servlets;
   
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.core.*;
   import java.io.*;
   import java.net.*;
   import java.util.*;
  @@ -80,15 +81,135 @@
    */
   public class DefaultErrorPage extends HttpServlet {
   
  -    public void service(HttpServletRequest request,
  -			HttpServletResponse response)
  +    public void service(HttpServletRequest requestH,
  +			HttpServletResponse responseH)
   	throws ServletException, IOException
       {
  -	StringWriter sw = new StringWriter();
  -	PrintWriter pw = new PrintWriter(sw);
  +	Request request=((HttpServletRequestFacade)requestH).getRealRequest();
  +	Response response=request.getResponse();
  +
  +	// use internal APIs - we can avoid them,but it's easier and faster
  +	int status=response.getStatus();
  +	String msg=(String)request.getAttribute("javax.servlet.error.message");
   
   	Throwable e= (Throwable)request.getAttribute("tomcat.error.throwable");
  +	if( e!=null ) {
  +	    sendError(request, response, 500, exceptionString( e ));
  +	    return;
  +	}
  +
  +	if( status==HttpServletResponse.SC_MOVED_TEMPORARILY) {
  +	    redirect( request, response, msg);
  +	} else {
  +	    sendError( request, response, status, msg);
  +
  +	}
  +    }
  +
  +    // -------------------- Redirect to error page if any --------------------
  +    public void sendError(Request request, Response response, int sc, String msg) throws IOException {
  +	response.setStatus(sc);
  +	Context context = request.getContext();
  +
  +	if (context == null) {
  +	    sendPrivateError(request, response, sc, msg);
  +	    return;
  +	}
  +
  +	String path = context.getErrorPage(String.valueOf(sc));
  +	//System.out.println("X " + path + " " + request + " " + response + " " + (path==null));
  +	if (path == null) {
  +	    sendPrivateError(request, response, sc, msg);
  +	    return;
  +	}
   	
  +	RequestDispatcher rd = context.getRequestDispatcher(path);
  +	if( rd==null) {
  +	    //  System.out.println("No error page for " + path);
  +	    sendPrivateError( request, response, sc, msg);
  +	    return;
  +	}
  +	
  +	try {
  +	    if( response.isStarted() )
  +		rd.forward(request.getFacade(), response.getFacade());
  +	    else
  +		rd.include(request.getFacade(), response.getFacade());
  +	} catch (ServletException se) {
  +	    sendPrivateError(request, response, sc, msg);
  +	}
  +
  +	// XXX
  +	// we only should set this if we are the head, not in an include
  +    }
  +
  +    // -------------------- Default error page --------------------
  +    private void sendPrivateError(Request request, Response response, int sc, String msg) throws IOException {
  +	response.setContentType("text/html");
  +
  +	StringBuffer buf = new StringBuffer();
  +	buf.append("<h1>Error: " + sc + "</h1>\r\n");
  +	buf.append(msg + "\r\n");
  +
  +	if( response.isUsingStream() ) {
  +	    ServletOutputStream out = response.getOutputStream();
  +	    out.print(buf.toString());
  +	} else {
  +	    PrintWriter out = response.getWriter();
  +	    out.print(buf.toString());
  +	}
  +    }
  +
  +    // -------------------- Redirect page --------------------
  +    public void redirect(Request request, Response response, String location) throws IOException {
  +        location = makeAbsolute(request, location);
  +	response.setContentType("text/html");	// ISO-8859-1 default
  +	response.setHeader("Location", location);
  +
  +	StringBuffer buf = new StringBuffer();
  +	buf.append("<head><title>Document moved</title></head>\r\n");
  +	buf.append("<body><h1>Document moved</h1>\r\n");
  +	buf.append("This document has moved <a href=\"");
  +	buf.append(location);
  +	buf.append("\">here</a>.<p>\r\n");
  +	buf.append("</body>\r\n");
  +
  +	String body = buf.toString();
  +
  +	response.setContentLength(body.length());
  +
  +	if( response.isUsingStream() ) {
  +	    ServletOutputStream out = response.getOutputStream();
  +	    out.print(body);
  +	} else {
  +	    PrintWriter out = response.getWriter();
  +	    out.print(body);
  +	}
  +    }
  +
  +    private String makeAbsolute(Request request, 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(request.getFacade()).toString();
  +	    try {
  +	        url = new URL(new URL(requrl), location);
  +	    }
  +	    catch (MalformedURLException ignored) {
  +	        // Give up
  +	        return location;
  +	    }
  +	}
  +        return url.toString();
  +    }
  +
  +    // -------------------- Internal error page  --------------------
  +    public String exceptionString( Throwable e) {
  +	StringWriter sw = new StringWriter();
  +	PrintWriter pw = new PrintWriter(sw);
   	pw.println("<b>Internal Servlet Error:</b><br>");
           pw.println("<pre>");
   	if( e != null ) 
  @@ -98,10 +219,10 @@
           if (e instanceof ServletException) {
   	    printRootCause((ServletException) e, pw);
   	}
  -	
  -	response.sendError(500, sw.toString());
  +	return sw.toString();
       }
  -
  +	
  +	
       /** A bit of recursion - print all traces in the stack
        */
       void printRootCause(ServletException e, PrintWriter out) {
  @@ -118,4 +239,6 @@
   	    }
   	}
       }
  +
  +
   }
  
  
  
  1.5       +1 -1      jakarta-tomcat/src/share/org/apache/tomcat/servlets/DefaultServlet.java
  
  Index: DefaultServlet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/servlets/DefaultServlet.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DefaultServlet.java	2000/01/30 04:22:47	1.4
  +++ DefaultServlet.java	2000/02/01 07:37:40	1.5
  @@ -81,7 +81,7 @@
       ServletContext contextF;
       private Context context;
       String docBase;
  -    int debug=1;
  +    int debug=0;
       
       public void init() throws ServletException {
   	contextF = getServletContext();