/*
 * 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 org.apache.jasper.runtime;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyContent;

import org.apache.jasper.Constants;

/**
 * Write text to a character-output stream, buffering characters so as
 * to provide for the efficient writing of single characters, arrays,
 * and strings. 
 *
 * Provide support for discarding for the output that has been buffered. 
 *
 * @author Rajiv Mordani
 * @author Jan Luehe
 */
public class BodyContentImpl extends BodyContent {
    
    private static final String LINE_SEPARATOR = 
        System.getProperty("line.separator");
    private static final boolean LIMIT_BUFFER = 
        Boolean.valueOf(System.getProperty("org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER", "false")).booleanValue();
    
    private char[] cb;
    private int nextChar;
    private boolean closed;
    
    // Enclosed writer to which any output is written
    private Writer writer;
    
    // See comment in setWriter()
    private int bufferSizeSave;
    
    /**
     * Constructor.
     */
    public BodyContentImpl(JspWriter enclosingWriter) {
        super(enclosingWriter);
        bufferSize = Constants.DEFAULT_TAG_BUFFER_SIZE;
        cb = new char[bufferSize];
        nextChar = 0;
        closed = false;
    }
    
    /**
     * Write a single character.
     */
    public void write(int c) throws IOException {
        if (writer != null) {
            writer.write(c);
        } else {
            ensureOpen();
            if (nextChar >= bufferSize) {
                reAllocBuff (1);
            }
            cb[nextChar++] = (char) c;
        }
    }
    
    /**
     * Write a portion of an array of characters.
     *
     * <p> Ordinarily this method stores characters from the given array into
     * this stream's buffer, flushing the buffer to the underlying stream as
     * needed.  If the requested length is at least as large as the buffer,
     * however, then this method will flush the buffer and write the characters
     * directly to the underlying stream.  Thus redundant
     * <code>DiscardableBufferedWriter</code>s will not copy data
     * unnecessarily.
     *
     * @param cbuf A character array
     * @param off Offset from which to start reading characters
     * @param len Number of characters to write
     */
    public void write(char[] cbuf, int off, int len) throws IOException {
        if (writer != null) {
            writer.write(cbuf, off, len);
        } else {
            ensureOpen();
            
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                    ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return;
            } 
            
            if (len >= bufferSize - nextChar)
                reAllocBuff (len);
            
            System.arraycopy(cbuf, off, cb, nextChar, len);
            nextChar+=len;
        }
    }
    
    /**
     * Write an array of characters.  This method cannot be inherited from the
     * Writer class because it must suppress I/O exceptions.
     */
    public void write(char[] buf) throws IOException {
        if (writer != null) {
            writer.write(buf);
        } else {
            write(buf, 0, buf.length);
        }
    }
    
    /**
     * Write a portion of a String.
     *
     * @param s String to be written
     * @param off Offset from which to start reading characters
     * @param len Number of characters to be written
     */
    public void write(String s, int off, int len) throws IOException {
        if (writer != null) {
            writer.write(s, off, len);
        } else {
            ensureOpen();
            if (len >= bufferSize - nextChar)
                reAllocBuff(len);
            
            s.getChars(off, off + len, cb, nextChar);
            nextChar += len;
        }
    }
    
    /**
     * Write a string.  This method cannot be inherited from the Writer class
     * because it must suppress I/O exceptions.
     */
    public void write(String s) throws IOException {
        if (writer != null) {
            writer.write(s);
        } else {
            write(s, 0, s.length());
        }
    }
    
    /**
     * Write a line separator.  The line separator string is defined by the
     * system property <tt>line.separator</tt>, and is not necessarily a single
     * newline ('\n') character.
     *
     * @throws IOException If an I/O error occurs
     */
    public void newLine() throws IOException {
        if (writer != null) {
            writer.write(LINE_SEPARATOR);
        } else {
            write(LINE_SEPARATOR);
        }
    }
    
    /**
     * Print a boolean value.  The string produced by <code>{@link
     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the <code>{@link
     * #write(int)}</code> method.
     *
     * @param b The <code>boolean</code> to be printed
     * @throws IOException
     */
    public void print(boolean b) throws IOException {
        if (writer != null) {
            writer.write(b ? "true" : "false");
        } else {
            write(b ? "true" : "false");
        }
    }
    
    /**
     * Print a character.  The character is translated into one or more bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the <code>{@link
     * #write(int)}</code> method.
     *
     * @param c The <code>char</code> to be printed
     * @throws IOException
     */
    public void print(char c) throws IOException {
        if (writer != null) {
            writer.write(String.valueOf(c));
        } else {
            write(String.valueOf(c));
        }
    }
    
    /**
     * Print an integer.  The string produced by <code>{@link
     * java.lang.String#valueOf(int)}</code> is translated into bytes according
     * to the platform's default character encoding, and these bytes are
     * written in exactly the manner of the <code>{@link #write(int)}</code>
     * method.
     *
     * @param i The <code>int</code> to be printed
     * @throws IOException
     */
    public void print(int i) throws IOException {
        if (writer != null) {
            writer.write(String.valueOf(i));
        } else {
            write(String.valueOf(i));
        }
    }
    
    /**
     * Print a long integer.  The string produced by <code>{@link
     * java.lang.String#valueOf(long)}</code> is translated into bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the
     * <code>{@link #write(int)}</code> method.
     *
     * @param l The <code>long</code> to be printed
     * @throws IOException
     */
    public void print(long l) throws IOException {
        if (writer != null) {
            writer.write(String.valueOf(l));
        } else {
            write(String.valueOf(l));
        }
    }
    
    /**
     * Print a floating-point number.  The string produced by <code>{@link
     * java.lang.String#valueOf(float)}</code> is translated into bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the
     * <code>{@link #write(int)}</code> method.
     *
     * @param f The <code>float</code> to be printed
     * @throws IOException
     */
    public void print(float f) throws IOException {
        if (writer != null) {
            writer.write(String.valueOf(f));
        } else {
            write(String.valueOf(f));
        }
    }
    
    /**
     * Print a double-precision floating-point number.  The string produced by
     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
     * bytes according to the platform's default character encoding, and these
     * bytes are written in exactly the manner of the <code>{@link
     * #write(int)}</code> method.
     *
     * @param d The <code>double</code> to be printed
     * @throws IOException
     */
    public void print(double d) throws IOException {
        if (writer != null) {
            writer.write(String.valueOf(d));
        } else {
            write(String.valueOf(d));
        }
    }
    
    /**
     * Print an array of characters.  The characters are converted into bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the
     * <code>{@link #write(int)}</code> method.
     *
     * @param s The array of chars to be printed
     *
     * @throws NullPointerException If <code>s</code> is <code>null</code>
     * @throws IOException
     */
    public void print(char[] s) throws IOException {
        if (writer != null) {
            writer.write(s);
        } else {
            write(s);
        }
    }
    
    /**
     * Print a string.  If the argument is <code>null</code> then the string
     * <code>"null"</code> is printed.  Otherwise, the string's characters are
     * converted into bytes according to the platform's default character
     * encoding, and these bytes are written in exactly the manner of the
     * <code>{@link #write(int)}</code> method.
     *
     * @param s The <code>String</code> to be printed
     * @throws IOException
     */
    public void print(String s) throws IOException {
        if (s == null) s = "null";
        if (writer != null) {
            writer.write(s);
        } else {
            write(s);
        }
    }
    
    /**
     * Print an object.  The string produced by the <code>{@link
     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
     * according to the platform's default character encoding, and these bytes
     * are written in exactly the manner of the
     * <code>{@link #write(int)}</code> method.
     *
     * @param obj The <code>Object</code> to be printed
     * @throws IOException
     */
    public void print(Object obj) throws IOException {
        if (writer != null) {
            writer.write(String.valueOf(obj));
        } else {
            write(String.valueOf(obj));
        }
    }
    
    /**
     * Terminate the current line by writing the line separator string.  The
     * line separator string is defined by the system property
     * <code>line.separator</code>, and is not necessarily a single newline
     * character (<code>'\n'</code>).
     *
     * @throws IOException
     */
    public void println() throws IOException {
        newLine();
    }
    
    /**
     * Print a boolean value and then terminate the line.  This method behaves
     * as though it invokes <code>{@link #print(boolean)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(boolean x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print a character and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(char)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(char x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print an integer and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(int)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(int x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print a long integer and then terminate the line.  This method behaves
     * as though it invokes <code>{@link #print(long)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(long x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print a floating-point number and then terminate the line.  This method
     * behaves as though it invokes <code>{@link #print(float)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(float x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print a double-precision floating-point number and then terminate the
     * line.  This method behaves as though it invokes <code>{@link
     * #print(double)}</code> and then <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(double x) throws IOException{
        print(x);
        println();
    }
    
    /**
     * Print an array of characters and then terminate the line.  This method
     * behaves as though it invokes <code>{@link #print(char[])}</code> and
     * then <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(char x[]) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print a String and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(String)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(String x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Print an Object and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(Object)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @throws IOException
     */
    public void println(Object x) throws IOException {
        print(x);
        println();
    }
    
    /**
     * Clear the contents of the buffer. If the buffer has been already
     * been flushed then the clear operation shall throw an IOException
     * to signal the fact that some data has already been irrevocably 
     * written to the client response stream.
     *
     * @throws IOException If an I/O error occurs
     */
    public void clear() throws IOException {
        if (writer != null) {
            throw new IOException();
        } else {
            nextChar = 0;
            if (LIMIT_BUFFER && (cb.length > Constants.DEFAULT_TAG_BUFFER_SIZE)) {
                bufferSize = Constants.DEFAULT_TAG_BUFFER_SIZE;
                cb = new char[bufferSize];
            }
        }
    }
    
    /**
     * Clears the current contents of the buffer. Unlike clear(), this
     * mehtod will not throw an IOException if the buffer has already been
     * flushed. It merely clears the current content of the buffer and
     * returns.
     *
     * @throws IOException If an I/O error occurs
     */
    public void clearBuffer() throws IOException {
        if (writer == null) {
            this.clear();
        }
    }
    
    /**
     * Close the stream, flushing it first.  Once a stream has been closed,
     * further write() or flush() invocations will cause an IOException to be
     * thrown.  Closing a previously-closed stream, however, has no effect.
     *
     * @throws IOException If an I/O error occurs
     */
    public void close() throws IOException {
        if (writer != null) {
            writer.close();
        } else {
            closed = true;
        }
    }
    
    /**
     * @return the number of bytes unused in the buffer
     */
    public int getRemaining() {
        return (writer == null) ? bufferSize-nextChar : 0;
    }
    
    /**
     * Return the value of this BodyJspWriter as a Reader.
     * Note: this is after evaluation!!  There are no scriptlets,
     * etc in this stream.
     *
     * @return the value of this BodyJspWriter as a Reader
     */
    public Reader getReader() {
        return (writer == null) ? new CharArrayReader (cb, 0, nextChar) : null;
    }
    
    /**
     * Return the value of the BodyJspWriter as a String.
     * Note: this is after evaluation!!  There are no scriptlets,
     * etc in this stream.
     *
     * @return the value of the BodyJspWriter as a String
     */
    public String getString() {
        return (writer == null) ? new String(cb, 0, nextChar) : null;
    }
    
    /**
     * Write the contents of this BodyJspWriter into a Writer.
     * Subclasses are likely to do interesting things with the
     * implementation so some things are extra efficient.
     *
     * @param out The writer into which to place the contents of this body
     * evaluation
     */
    public void writeOut(Writer out) throws IOException {
        if (writer == null) {
            out.write(cb, 0, nextChar);
            // Flush not called as the writer passed could be a BodyContent and
            // it doesn't allow to flush.
        }
    }
    
    /**
     * Sets the writer to which all output is written.
     */
    void setWriter(Writer writer) {
        this.writer = writer;
        closed = false;
        if (writer != null) {
            // According to the spec, the JspWriter returned by 
            // JspContext.pushBody(java.io.Writer writer) must behave as
            // though it were unbuffered. This means that its getBufferSize()
            // must always return 0. The implementation of
            // JspWriter.getBufferSize() returns the value of JspWriter's
            // 'bufferSize' field, which is inherited by this class. 
            // Therefore, we simply save the current 'bufferSize' (so we can 
            // later restore it should this BodyContentImpl ever be reused by
            // a call to PageContext.pushBody()) before setting it to 0.
            if (bufferSize != 0) {
                bufferSizeSave = bufferSize;
                bufferSize = 0;
            }
        } else {
            bufferSize = bufferSizeSave;
            clearBody();
        }
    }
    
    private void ensureOpen() throws IOException {
        if (closed) throw new IOException("Stream closed");
    }
    
    /**
     * Reallocates buffer since the spec requires it to be unbounded.
     */
    private void reAllocBuff(int len) {
        
        if (bufferSize + len <= cb.length) {
            bufferSize = cb.length;
            return;
        }
        
        if (len < cb.length) {
            len = cb.length;
        }
        
        bufferSize = cb.length + len;
        char[] tmp = new char[bufferSize];
        
        System.arraycopy(cb, 0, tmp, 0, cb.length);
        cb = tmp;
        tmp = null;
        
    }
    
    
}
