/*
 * $Header: /home/cvspublic/jakarta-slide/src/webdav/server/org/apache/slide/webdav/logger/XHttpServletRequestFacade.java,v 1.6 2004/07/28 09:32:36 ib Exp $
 * $Revision: 1.6 $
 * $Date: 2004/07/28 09:32:36 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * Licensed 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 org.apache.slide.webdav.logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.slide.common.Domain;

/**
 * This class supports additional set-methods and a re-readable
 * inputstream to the interface javax.servlet.http.HttpServletRequest.
 *
 *            Christopher Lenz (cmlenz at apache.org)
 *
 * @version   0.1
 *
 * @invariant (inputStream != null)
 *
 * @see       javax.servlet.http.HttpServletRequest
 *
 */
public class XHttpServletRequestFacade extends HttpServletRequestWrapper {
        
            
    public static final String DEFAULT_CHAR_ENCODING = "8859_1";

    /**
     * the inputstream to re-read.
     *
     * @see java.io.BufferedInputStream
     */
    private XServletInputStreamFacade inStreamFacade = null;
            
    /**
     * buffered reader which uses the input stream
     *
     * @see java.io.BufferedReader
     */
    private BufferedReader reader = null;
        
    /**
     * true - if inputstream can read using a reader; false otherwise.
     */
    private boolean usingReader = false;

    /**
     * true - if inputstream can read using a stream; false otherwise.
     */
    private boolean usingStream = false;
        
        
    /**
     * This constructor creates an re-readable HttpServletRequest.
     *
     * @pre        (req != null)
     * @post
     *
     * @param      req   HttpServletRequest
     *
     * @time
     * @space
     */
    public XHttpServletRequestFacade (HttpServletRequest request)  {
        super(request);
        Domain.debug("Create XHttpServletRequestFacade");
    }

    /**
     * Retrieves the body of the request as binary data using a ServletInputStream.
     *
     * @param      none
     *
     * @return     Returns the body of the request
     */
    public ServletInputStream getInputStream() throws IOException {
        Domain.debug("ENTER: XHttpServletRequestFacade:getInputStream()");
        if (usingReader) {
            throw new IllegalStateException("getReader() method has been called on this request");
        }
        usingStream = true;
        
        if ( inStreamFacade == null ) {
            inStreamFacade = new XServletInputStreamFacade( super.getInputStream());
        }
            
        Domain.debug("LEAVE: XHttpServletRequestFacade:getInputStream()");
        return (  inStreamFacade );
    }

        
    /**
     *  Reads the next byte of data from the input stream.
     *
     * @param      none
     *
     * @return     the next byte of data, or -1 if the end of the stream is reached
     */
    public int doRead() throws IOException {
        return inStreamFacade.read();
    }

    /**
     *  Reads up to len bytes of data from the input stream into an array of bytes.
     *
     * @param      b - the buffer into which the data is read.
     * @param      off - the start offset in array b at which the data is written.
     * @param      len - the maximum number of bytes to read.
     *
     * @return     the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.
     */
    public int doRead( byte b[], int off, int len ) throws IOException {
        return inStreamFacade.read( b, off, len );
    }

        
    /**
     * Retrieves the body of the request as character data using a BufferedReader.
     *
     * @param      none
     *
     * @return     Returns a BufferedReader
     */
    public BufferedReader getReader() throws IOException {
        Domain.debug("ENTER: XHttpServletRequestFacade:getReader()");
        if (usingStream) {
            throw new IllegalStateException("getInputStream() method has been called on this request");
        }
        usingReader = true;

        if ( inStreamFacade == null ) {
            inStreamFacade = new XServletInputStreamFacade( super.getInputStream());
        }

        if( reader != null ) {
            Domain.debug("LEAVE: XHttpServletRequestFacade:getReader() - reader != null");
            return reader; // method already called
        }

        String encoding = super.getCharacterEncoding();
        if (encoding == null) {
            encoding = DEFAULT_CHAR_ENCODING;
        }
    
        InputStreamReader r = new InputStreamReader(inStreamFacade, encoding);
        reader= new BufferedReader(r);
        Domain.debug("LEAVE: XHttpServletRequestFacade:getReader() - new BufferedReader");
        return reader;
    }

    /**
     * Returns the content of the buffered input stream.
     *
     * @return      copy of input stream as string.
     */
    public String getRequestBody() throws IOException {
        if ( usingStream ){
            Domain.debug("XHttpServletRequestFacade:getRequestBody() - usingStream");
            return inStreamFacade.getBufferContent();
        } else if ( usingReader ) {
            Domain.debug("XHttpServletRequestFacade:getRequestBody() - usingReader");
            return reader.toString();
        } else {
            Domain.debug("XHttpServletRequestFacade:getRequestBody() - nor Reader nor Stream - do nothing");
            return "";
        }
    }
}
