/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.servlet.http;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;


/**
 *
 * Provides an abstract class to be subclassed to create
 * an HTTP servlet suitable for a Web site. A subclass of
 * <code>HttpServlet</code> must override at least 
 * one method, usually one of these:
 *
 * <ul>
 * <li> <code>doGet</code>, if the servlet supports HTTP GET requests
 * <li> <code>doPost</code>, for HTTP POST requests
 * <li> <code>doPut</code>, for HTTP PUT requests
 * <li> <code>doDelete</code>, for HTTP DELETE requests
 * <li> <code>init</code> and <code>destroy</code>, 
 * to manage resources that are held for the life of the servlet
 * <li> <code>getServletInfo</code>, which the servlet uses to
 * provide information about itself 
 * </ul>
 *
 * <p>There's almost no reason to override the <code>service</code>
 * method. <code>service</code> handles standard HTTP
 * requests by dispatching them to the handler methods
 * for each HTTP request type (the <code>do</code><i>XXX</i>
 * methods listed above).
 *
 * <p>Likewise, there's almost no reason to override the 
 * <code>doOptions</code> and <code>doTrace</code> methods.
 * 
 * <p>Servlets typically run on multithreaded servers,
 * so be aware that a servlet must handle concurrent
 * requests and be careful to synchronize access to shared resources.
 * Shared resources include in-memory data such as
 * instance or class variables and external objects
 * such as files, database connections, and network 
 * connections.
 * See the
 * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">
 * Java Tutorial on Multithreaded Programming</a> for more
 * information on handling multiple threads in a Java program.
 *
 * @author	Various
 * @version	$Version$
 *
 */



public abstract class HttpServlet extends GenericServlet
    implements java.io.Serializable
{
    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";

    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";
    
    private static final String LSTRING_FILE =
	"javax.servlet.http.LocalStrings";
    private static ResourceBundle lStrings =
	ResourceBundle.getBundle(LSTRING_FILE);
   
   
   
    
    /**
     * Does nothing, because this is an abstract class.
     * 
     */

    public HttpServlet() { }
    
    

    /**
     *
     * Called by the server (via the <code>service</code> method) to
     * allow a servlet to handle a GET request. 
     *
     * <p>Overriding this method to support a GET request also
     * automatically supports an HTTP HEAD request. A HEAD
     * request is a GET request that returns no body in the
     * response, only the request header fields.
     *
     * <p>When overriding this method, read the request data,
     * write the response headers, get the response's writer or 
     * output stream object, and finally, write the response data.
     * It's best to include content type and encoding. When using
     * a <code>PrintWriter</code> object to return the response,
     * set the content type before accessing the
     * <code>PrintWriter</code> object.
     *
     * <p>The servlet container must write the headers before
     * committing the response, because in HTTP the headers must be sent
     * before the response body.
     *
     * <p>Where possible, set the Content-Length header (with the
     * {@link javax.servlet.ServletResponse#setContentLength} method),
     * to allow the servlet container to use a persistent connection 
     * to return its response to the client, improving performance.
     * The content length is automatically set if the entire response fits
     * inside the response buffer.
     *
     * <p>When using HTTP 1.1 chunked encoding (which means that the response
     * has a Transfer-Encoding header), do not set the Content-Length header.
     *
     * <p>The GET method should be safe, that is, without
     * any side effects for which users are held responsible.
     * For example, most form queries have no side effects.
     * If a client request is intended to change stored data,
     * the request should use some other HTTP method.
     *
     * <p>The GET method should also be idempotent, meaning
     * that it can be safely repeated. Sometimes making a
     * method safe also makes it idempotent. For example, 
     * repeating queries is both safe and idempotent, but
     * buying a product online or modifying data is neither
     * safe nor idempotent. 
     *
     * <p>If the request is incorrectly formatted, <code>doGet</code>
     * returns an HTTP "Bad Request" message.
     * 
     *
     * @param req	an {@link HttpServletRequest} object that
     *			contains the request the client has made
     *			of the servlet
     *
     * @param resp	an {@link HttpServletResponse} object that
     *			contains the response the servlet sends
     *			to the client
     * 
     * @exception IOException	if an input or output error is 
     *				detected when the servlet handles
     *				the GET request
     *
     * @exception ServletException	if the request for the GET
     *					could not be handled
     *
     * 
     * @see javax.servlet.ServletResponse#setContentType
     *
     */

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	String protocol = req.getProtocol();
	String msg = lStrings.getString("http.method_get_not_supported");
	if (protocol.endsWith("1.1")) {
	    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
	} else {
	    resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
	}
    }





    /**
     *
     * Returns the time the <code>HttpServletRequest</code>
     * object was last modified,
     * in milliseconds since midnight January 1, 1970 GMT.
     * If the time is unknown, this method returns a negative
     * number (the default).
     *
     * <p>Servlets that support HTTP GET requests and can quickly determine
     * their last modification time should override this method.
     * This makes browser and proxy caches work more effectively,
     * reducing the load on server and network resources.
     *
     *
     * @param req	the <code>HttpServletRequest</code> 
     *			object that is sent to the servlet
     *
     * @return		a <code>long</code> integer specifying
     *			the time the <code>HttpServletRequest</code>
     *			object was last modified, in milliseconds
     *			since midnight, January 1, 1970 GMT, or
     *			-1 if the time is not known
     *
     */

    protected long getLastModified(HttpServletRequest req) {
	return -1;
    }




    /**
     * 
     *
     * <p>Receives an HTTP HEAD request from the protected
     * <code>service</code> method and handles the
     * request.
     * The client sends a HEAD request when it wants
     * to see only the headers of a response, such as
     * Content-Type or Content-Length. The HTTP HEAD
     * method counts the output bytes in the response
     * to set the Content-Length header accurately.
     *
     * <p>If you override this method, you can avoid computing
     * the response body and just set the response headers
     * directly to improve performance. Make sure that the
     * <code>doHead</code> method you write is both safe
     * and idempotent (that is, protects itself from being
     * called multiple times for one HTTP HEAD request).
     *
     * <p>If the HTTP HEAD request is incorrectly formatted,
     * <code>doHead</code> returns an HTTP "Bad Request"
     * message.
     *
     *
     * @param req	the request object that is passed
     *			to the servlet
     *			
     * @param resp	the response object that the servlet
     *			uses to return the headers to the clien
     *
     * @exception IOException		if an input or output error occurs
     *
     * @exception ServletException	if the request for the HEAD
     *					could not be handled
     */

    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	NoBodyResponse response = new NoBodyResponse(resp);
	
	doGet(req, response);
	response.setContentLength();
    }
    




    /**
     *
     * Called by the server (via the <code>service</code> method)
     * to allow a servlet to handle a POST request.
     *
     * The HTTP POST method allows the client to send
     * data of unlimited length to the Web server a single time
     * and is useful when posting information such as
     * credit card numbers.
     *
     * <p>When overriding this method, read the request data,
     * write the response headers, get the response's writer or output
     * stream object, and finally, write the response data. It's best 
     * to include content type and encoding. When using a
     * <code>PrintWriter</code> object to return the response, set the 
     * content type before accessing the <code>PrintWriter</code> object. 
     *
     * <p>The servlet container must write the headers before committing the
     * response, because in HTTP the headers must be sent before the 
     * response body.
     *
     * <p>Where possible, set the Content-Length header (with the
     * {@link javax.servlet.ServletResponse#setContentLength} method),
     * to allow the servlet container to use a persistent connection 
     * to return its response to the client, improving performance.
     * The content length is automatically set if the entire response fits
     * inside the response buffer.  
     *
     * <p>When using HTTP 1.1 chunked encoding (which means that the response
     * has a Transfer-Encoding header), do not set the Content-Length header. 
     *
     * <p>This method does not need to be either safe or idempotent.
     * Operations requested through POST can have side effects for
     * which the user can be held accountable, for example, 
     * updating stored data or buying items online.
     *
     * <p>If the HTTP POST request is incorrectly formatted,
     * <code>doPost</code> returns an HTTP "Bad Request" message.
     *
     *
     * @param req	an {@link HttpServletRequest} object that
     *			contains the request the client has made
     *			of the servlet
     *
     * @param resp	an {@link HttpServletResponse} object that
     *			contains the response the servlet sends
     *			to the client
     * 
     * @exception IOException	if an input or output error is 
     *				detected when the servlet handles
     *				the request
     *
     * @exception ServletException	if the request for the POST
     *					could not be handled
     *
     *
     * @see javax.servlet.ServletOutputStream
     * @see javax.servlet.ServletResponse#setContentType
     *
     *
     */

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	String protocol = req.getProtocol();
	String msg = lStrings.getString("http.method_post_not_supported");
	if (protocol.endsWith("1.1")) {
	    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
	} else {
	    resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
	}
    }




    /**
     * Called by the server (via the <code>service</code> method)
     * to allow a servlet to handle a PUT request.
     *
     * The PUT operation allows a client to 
     * place a file on the server and is similar to 
     * sending a file by FTP.
     *
     * <p>When overriding this method, leave intact
     * any content headers sent with the request (including
     * Content-Length, Content-Type, Content-Transfer-Encoding,
     * Content-Encoding, Content-Base, Content-Language, Content-Location,
     * Content-MD5, and Content-Range). If your method cannot
     * handle a content header, it must issue an error message
     * (HTTP 501 - Not Implemented) and discard the request.
     * For more information on HTTP 1.1, see RFC 2616
     * <a href="http://www.ietf.org/rfc/rfc2616.txt"></a>.
     *
     * <p>This method does not need to be either safe or idempotent.
     * Operations that <code>doPut</code> performs can have side
     * effects for which the user can be held accountable. When using
     * this method, it may be useful to save a copy of the
     * affected URL in temporary storage.
     *
     * <p>If the HTTP PUT request is incorrectly formatted,
     * <code>doPut</code> returns an HTTP "Bad Request" message.
     *
     *
     * @param req	the {@link HttpServletRequest} object that
     *			contains the request the client made of
     *			the servlet
     *
     * @param resp	the {@link HttpServletResponse} object that
     *			contains the response the servlet returns
     *			to the client
     *
     * @exception IOException	if an input or output error occurs
     *				while the servlet is handling the
     *				PUT request
     *
     * @exception ServletException	if the request for the PUT
     *					cannot be handled
     *
     */
  
    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	String protocol = req.getProtocol();
	String msg = lStrings.getString("http.method_put_not_supported");
	if (protocol.endsWith("1.1")) {
	    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
	} else {
	    resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
	}
    }




    /**
     * 
     * Called by the server (via the <code>service</code> method)
     * to allow a servlet to handle a DELETE request.
     *
     * The DELETE operation allows a client to remove a document
     * or Web page from the server.
     * 
     * <p>This method does not need to be either safe
     * or idempotent. Operations requested through
     * DELETE can have side effects for which users
     * can be held accountable. When using
     * this method, it may be useful to save a copy of the
     * affected URL in temporary storage.
     *
     * <p>If the HTTP DELETE request is incorrectly formatted,
     * <code>doDelete</code> returns an HTTP "Bad Request"
     * message.
     *
     *
     * @param req	the {@link HttpServletRequest} object that
     *			contains the request the client made of
     *			the servlet
     *
     *
     * @param resp	the {@link HttpServletResponse} object that
     *			contains the response the servlet returns
     *			to the client				
     *
     *
     * @exception IOException	if an input or output error occurs
     *				while the servlet is handling the
     *				DELETE request
     *
     * @exception ServletException	if the request for the
     *					DELETE cannot be handled
     *
     */
     
    protected void doDelete(HttpServletRequest req,
			    HttpServletResponse resp)
	throws ServletException, IOException
    {
	String protocol = req.getProtocol();
	String msg = lStrings.getString("http.method_delete_not_supported");
	if (protocol.endsWith("1.1")) {
	    resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
	} else {
	    resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
	}
    }
    

    private static Method[] getAllDeclaredMethods(Class c) {

        if (c.equals(javax.servlet.http.HttpServlet.class)) {
            return null;
        }

        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
        Method[] thisMethods = c.getDeclaredMethods();
	
        if ((parentMethods != null) && (parentMethods.length > 0)) {
            Method[] allMethods =
                new Method[parentMethods.length + thisMethods.length];
	    System.arraycopy(parentMethods, 0, allMethods, 0,
                             parentMethods.length);
	    System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
                             thisMethods.length);

	    thisMethods = allMethods;
	}

	return thisMethods;
    }


    /**
     * Called by the server (via the <code>service</code> method)
     * to allow a servlet to handle a OPTIONS request.
     *
     * The OPTIONS request determines which HTTP methods 
     * the server supports and
     * returns an appropriate header. For example, if a servlet
     * overrides <code>doGet</code>, this method returns the
     * following header:
     *
     * <p><code>Allow: GET, HEAD, TRACE, OPTIONS</code>
     *
     * <p>There's no need to override this method unless the
     * servlet implements new HTTP methods, beyond those 
     * implemented by HTTP 1.1.
     *
     * @param req	the {@link HttpServletRequest} object that
     *			contains the request the client made of
     *			the servlet
     *
     *
     * @param resp	the {@link HttpServletResponse} object that
     *			contains the response the servlet returns
     *			to the client				
     *
     *
     * @exception IOException	if an input or output error occurs
     *				while the servlet is handling the
     *				OPTIONS request
     *
     * @exception ServletException	if the request for the
     *					OPTIONS cannot be handled
     *
     */
         
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	Method[] methods = getAllDeclaredMethods(this.getClass());
	
	boolean ALLOW_GET = false;
	boolean ALLOW_HEAD = false;
	boolean ALLOW_POST = false;
	boolean ALLOW_PUT = false;
	boolean ALLOW_DELETE = false;
	boolean ALLOW_TRACE = true;
	boolean ALLOW_OPTIONS = true;
	
	for (int i=0; i<methods.length; i++) {
	    Method m = methods[i];
	    
	    if (m.getName().equals("doGet")) {
		ALLOW_GET = true;
		ALLOW_HEAD = true;
	    }
	    if (m.getName().equals("doPost")) 
		ALLOW_POST = true;
	    if (m.getName().equals("doPut"))
		ALLOW_PUT = true;
	    if (m.getName().equals("doDelete"))
		ALLOW_DELETE = true;
	    
	}
	
	String allow = null;
	if (ALLOW_GET)
	    if (allow==null) allow=METHOD_GET;
	if (ALLOW_HEAD)
	    if (allow==null) allow=METHOD_HEAD;
	    else allow += ", " + METHOD_HEAD;
	if (ALLOW_POST)
	    if (allow==null) allow=METHOD_POST;
	    else allow += ", " + METHOD_POST;
	if (ALLOW_PUT)
	    if (allow==null) allow=METHOD_PUT;
	    else allow += ", " + METHOD_PUT;
	if (ALLOW_DELETE)
	    if (allow==null) allow=METHOD_DELETE;
	    else allow += ", " + METHOD_DELETE;
	if (ALLOW_TRACE)
	    if (allow==null) allow=METHOD_TRACE;
	    else allow += ", " + METHOD_TRACE;
	if (ALLOW_OPTIONS)
	    if (allow==null) allow=METHOD_OPTIONS;
	    else allow += ", " + METHOD_OPTIONS;
	
	resp.setHeader("Allow", allow);
    }
    
    
    
    
    /**
     * Called by the server (via the <code>service</code> method)
     * to allow a servlet to handle a TRACE request.
     *
     * A TRACE returns the headers sent with the TRACE
     * request to the client, so that they can be used in
     * debugging. There's no need to override this method. 
     *
     *
     *
     * @param req	the {@link HttpServletRequest} object that
     *			contains the request the client made of
     *			the servlet
     *
     *
     * @param resp	the {@link HttpServletResponse} object that
     *			contains the response the servlet returns
     *			to the client				
     *
     *
     * @exception IOException	if an input or output error occurs
     *				while the servlet is handling the
     *				TRACE request
     *
     * @exception ServletException	if the request for the
     *					TRACE cannot be handled
     *
     */

    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) 
	throws ServletException, IOException
    {
	
	int responseLength;
	
	String CRLF = "\r\n";
	String responseString = "TRACE "+ req.getRequestURI()+
	    " " + req.getProtocol();
	
	Enumeration reqHeaderEnum = req.getHeaderNames();
	
	while( reqHeaderEnum.hasMoreElements() ) {
	    String headerName = (String)reqHeaderEnum.nextElement();
	    responseString += CRLF + headerName + ": " +
		req.getHeader(headerName); 
	}
	
	responseString += CRLF;
	
	responseLength = responseString.length();
	
	resp.setContentType("message/http");
	resp.setContentLength(responseLength);
	ServletOutputStream out = resp.getOutputStream();
	out.print(responseString);	
	out.close();
	return;
    }		





    /**
     *
     * Receives standard HTTP requests from the public
     * <code>service</code> method and dispatches
     * them to the <code>do</code><i>XXX</i> methods defined in 
     * this class. This method is an HTTP-specific version of the 
     * {@link javax.servlet.Servlet#service} method. There's no
     * need to override this method.
     *
     *
     *
     * @param req	the {@link HttpServletRequest} object that
     *			contains the request the client made of
     *			the servlet
     *
     *
     * @param resp	the {@link HttpServletResponse} object that
     *			contains the response the servlet returns
     *			to the client				
     *
     *
     * @exception IOException	if an input or output error occurs
     *				while the servlet is handling the
     *				HTTP request
     *
     * @exception ServletException	if the HTTP request
     *					cannot be handled
     * 
     * @see 				javax.servlet.Servlet#service
     *
     */

    protected void service(HttpServletRequest req, HttpServletResponse resp)
	throws ServletException, IOException
    {
	String method = req.getMethod();

	if (method.equals(METHOD_GET)) {
	    long lastModified = getLastModified(req);
	    if (lastModified == -1) {
		// servlet doesn't support if-modified-since, no reason
		// to go through further expensive logic
		doGet(req, resp);
	    } else {
		long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
		if (ifModifiedSince < (lastModified / 1000 * 1000)) {
		    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
		    maybeSetLastModified(resp, lastModified);
		    doGet(req, resp);
		} else {
		    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
		}
	    }

	} else if (method.equals(METHOD_HEAD)) {
	    long lastModified = getLastModified(req);
	    maybeSetLastModified(resp, lastModified);
	    doHead(req, resp);

	} else if (method.equals(METHOD_POST)) {
	    doPost(req, resp);
	    
	} else if (method.equals(METHOD_PUT)) {
	    doPut(req, resp);	
	    
	} else if (method.equals(METHOD_DELETE)) {
	    doDelete(req, resp);
	    
	} else if (method.equals(METHOD_OPTIONS)) {
	    doOptions(req,resp);
	    
	} else if (method.equals(METHOD_TRACE)) {
	    doTrace(req,resp);
	    
	} else {
	    //
	    // Note that this means NO servlet supports whatever
	    // method was requested, anywhere on this server.
	    //

	    String errMsg = lStrings.getString("http.method_not_implemented");
	    Object[] errArgs = new Object[1];
	    errArgs[0] = method;
	    errMsg = MessageFormat.format(errMsg, errArgs);
	    
	    resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
	}
    }
    




    /*
     * Sets the Last-Modified entity header field, if it has not
     * already been set and if the value is meaningful.  Called before
     * doGet, to ensure that headers are set before response data is
     * written.  A subclass might have set this header already, so we
     * check.
     */

    private void maybeSetLastModified(HttpServletResponse resp,
				      long lastModified) {
	if (resp.containsHeader(HEADER_LASTMOD))
	    return;
	if (lastModified >= 0)
	    resp.setDateHeader(HEADER_LASTMOD, lastModified);
    }
   
   
   
    
    /**
     *
     * Dispatches client requests to the protected
     * <code>service</code> method. There's no need to
     * override this method.
     *
     * 
     * @param req	the {@link HttpServletRequest} object that
     *			contains the request the client made of
     *			the servlet
     *
     *
     * @param res	the {@link HttpServletResponse} object that
     *			contains the response the servlet returns
     *			to the client				
     *
     *
     * @exception IOException	if an input or output error occurs
     *				while the servlet is handling the
     *				HTTP request
     *
     * @exception ServletException	if the HTTP request cannot
     *					be handled
     *
     * 
     * @see javax.servlet.Servlet#service
     *
     */

    public void service(ServletRequest req, ServletResponse res)
	throws ServletException, IOException
    {
	HttpServletRequest	request;
	HttpServletResponse	response;
	
	try {
	    request = (HttpServletRequest) req;
	    response = (HttpServletResponse) res;
	} catch (ClassCastException e) {
	    throw new ServletException("non-HTTP request or response");
	}
	service(request, response);
    }
}




/*
 * A response that includes no body, for use in (dumb) "HEAD" support.
 * This just swallows that body, counting the bytes in order to set
 * the content length appropriately.  All other methods delegate directly
 * to the HTTP Servlet Response object used to construct this one.
 */
// file private
class NoBodyResponse implements HttpServletResponse {
    private HttpServletResponse		resp;
    private NoBodyOutputStream		noBody;
    private PrintWriter			writer;
    private boolean			didSetContentLength;

    // file private
    NoBodyResponse(HttpServletResponse r) {
	resp = r;
	noBody = new NoBodyOutputStream();
    }

    // file private
    void setContentLength() {
	if (!didSetContentLength)
	  resp.setContentLength(noBody.getContentLength());
    }


    // SERVLET RESPONSE interface methods

    public void setContentLength(int len) {
	resp.setContentLength(len);
	didSetContentLength = true;
    }

    public void setCharacterEncoding(String charset)
      { resp.setCharacterEncoding(charset); }

    public void setContentType(String type)
      { resp.setContentType(type); }

    public String getContentType()
      { return resp.getContentType(); }

    public ServletOutputStream getOutputStream() throws IOException
      { return noBody; }

    public String getCharacterEncoding()
	{ return resp.getCharacterEncoding(); }

    public PrintWriter getWriter() throws UnsupportedEncodingException
    {
	if (writer == null) {
	    OutputStreamWriter	w;

	    w = new OutputStreamWriter(noBody, getCharacterEncoding());
	    writer = new PrintWriter(w);
	}
	return writer;
    }

    public void setBufferSize(int size) throws IllegalStateException
      { resp.setBufferSize(size); }

    public int getBufferSize()
      { return resp.getBufferSize(); }

    public void reset() throws IllegalStateException
      { resp.reset(); }
      
      public void resetBuffer() throws IllegalStateException
      { resp.resetBuffer(); }

    public boolean isCommitted()
      { return resp.isCommitted(); }

    public void flushBuffer() throws IOException
      { resp.flushBuffer(); }

    public void setLocale(Locale loc)
      { resp.setLocale(loc); }

    public Locale getLocale()
      { return resp.getLocale(); }


    // HTTP SERVLET RESPONSE interface methods

    public void addCookie(Cookie cookie)
      { resp.addCookie(cookie); }

    public boolean containsHeader(String name)
      { return resp.containsHeader(name); }

    /** @deprecated */
    public void setStatus(int sc, String sm)
      { resp.setStatus(sc, sm); }

    public void setStatus(int sc)
      { resp.setStatus(sc); }

    public void setHeader(String name, String value)
      { resp.setHeader(name, value); }

    public void setIntHeader(String name, int value)
      { resp.setIntHeader(name, value); }

    public void setDateHeader(String name, long date)
      { resp.setDateHeader(name, date); }

    public void sendError(int sc, String msg) throws IOException
      { resp.sendError(sc, msg); }

    public void sendError(int sc) throws IOException
      { resp.sendError(sc); }

    public void sendRedirect(String location) throws IOException
      { resp.sendRedirect(location); }
    
    public String encodeURL(String url) 
      { return resp.encodeURL(url); }

    public String encodeRedirectURL(String url)
      { return resp.encodeRedirectURL(url); }
      
    public void addHeader(String name, String value)
      { resp.addHeader(name, value); }
      
    public void addDateHeader(String name, long value)
      { resp.addDateHeader(name, value); }
      
    public void addIntHeader(String name, int value)
      { resp.addIntHeader(name, value); }
      
      
      

    /**
     * @deprecated	As of Version 2.1, replaced by
     * 			{@link HttpServletResponse#encodeURL}.
     *
     */
     
     
    public String encodeUrl(String url) 
      { return this.encodeURL(url); }
      
      
      
      
      
      
      

    /**
     * @deprecated	As of Version 2.1, replaced by
     *			{@link HttpServletResponse#encodeRedirectURL}.
     *
     */
     
     
    public String encodeRedirectUrl(String url)
      { return this.encodeRedirectURL(url); }

}







/*
 * Servlet output stream that gobbles up all its data.
 */
 
// file private
class NoBodyOutputStream extends ServletOutputStream {

    private static final String LSTRING_FILE =
	"javax.servlet.http.LocalStrings";
    private static ResourceBundle lStrings =
	ResourceBundle.getBundle(LSTRING_FILE);

    private int		contentLength = 0;

    // file private
    NoBodyOutputStream() {}

    // file private
    int getContentLength() {
	return contentLength;
    }

    public void write(int b) {
	contentLength++;
    }

    public void write(byte buf[], int offset, int len)
	throws IOException
    {
	if (len >= 0) {
	    contentLength += len;
	} else {
	    // XXX
	    // isn't this really an IllegalArgumentException?
	    
	    String msg = lStrings.getString("err.io.negativelength");
	    throw new IOException("negative length");
	}
    }
}
