/*
 * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.net.www.http;

import java.io.*;

/**
 * OutputStream that sends the output to the underlying stream using chunked
 * encoding as specified in RFC 2068.
 */
public class ChunkedOutputStream extends PrintStream {

    /* Default chunk size (including chunk header) if not specified */
    static final int DEFAULT_CHUNK_SIZE = 4096;
    private static final byte[] CRLF = {'\r', '\n'};
    private static final int CRLF_SIZE = CRLF.length;
    private static final byte[] FOOTER = CRLF;
    private static final int FOOTER_SIZE = CRLF_SIZE;
    private static final byte[] EMPTY_CHUNK_HEADER = getHeader(0);
    private static final int EMPTY_CHUNK_HEADER_SIZE = getHeaderSize(0);

    /* internal buffer */
    private byte buf[];
    /* size of data (excluding footers and headers) already stored in buf */
    private int size;
    /* current index in buf (i.e. buf[count] */
    private int count;
    /* number of bytes to be filled up to complete a data chunk
     * currently being built */
    private int spaceInCurrentChunk;

    /* underlying stream */
    private PrintStream out;

    /* the chunk size we use */
    private int preferredChunkDataSize;
    private int preferedHeaderSize;
    private int preferredChunkGrossSize;
    /* header for a complete Chunk */
    private byte[] completeHeader;

    /* return the size of the header for a particular chunk size */
    private static int getHeaderSize(int size) {
        return (Integer.toHexString(size)).length() + CRLF_SIZE;
    }

    /* return a header for a particular chunk size */
    private static byte[] getHeader(int size){
        try {
            String hexStr =  Integer.toHexString(size);
            byte[] hexBytes = hexStr.getBytes("US-ASCII");
            byte[] header = new byte[getHeaderSize(size)];
            for (int i=0; i<hexBytes.length; i++)
                header[i] = hexBytes[i];
            header[hexBytes.length] = CRLF[0];
            header[hexBytes.length+1] = CRLF[1];
            return header;
        } catch (java.io.UnsupportedEncodingException e) {
            /* This should never happen */
            throw new InternalError(e.getMessage());
        }
    }

    public ChunkedOutputStream(PrintStream o) {
        this(o, DEFAULT_CHUNK_SIZE);
    }

    public ChunkedOutputStream(PrintStream o, int size) {
        super(o);
        out = o;

        if (size <= 0) {
            size = DEFAULT_CHUNK_SIZE;
        }

        /* Adjust the size to cater for the chunk header - eg: if the
         * preferred chunk size is 1k this means the chunk size should
         * be 1017 bytes (differs by 7 from preferred size because of
         * 3 bytes for chunk size in hex and CRLF (header) and CRLF (footer)).
         *
         * If headerSize(adjusted_size) is shorter then headerSize(size)
         * then try to use the extra byte unless headerSize(adjusted_size+1)
         * increases back to headerSize(size)
         */
        if (size > 0) {
            int adjusted_size = size - getHeaderSize(size) - FOOTER_SIZE;
            if (getHeaderSize(adjusted_size+1) < getHeaderSize(size)){
                adjusted_size++;
            }
            size = adjusted_size;
        }

        if (size > 0) {
            preferredChunkDataSize = size;
        } else {
            preferredChunkDataSize = DEFAULT_CHUNK_SIZE -
                    getHeaderSize(DEFAULT_CHUNK_SIZE) - FOOTER_SIZE;
        }

        preferedHeaderSize = getHeaderSize(preferredChunkDataSize);
        preferredChunkGrossSize = preferedHeaderSize + preferredChunkDataSize
                + FOOTER_SIZE;
        completeHeader = getHeader(preferredChunkDataSize);

        /* start with an initial buffer */
        buf = new byte[preferredChunkDataSize + 32];
        reset();
    }

    /*
     * Flush a buffered, completed chunk to an underlying stream. If the data in
     * the buffer is insufficient to build up a chunk of "preferredChunkSize"
     * then the data do not get flushed unless flushAll is true. If flushAll is
     * true then the remaining data builds up a last chunk which size is smaller
     * than preferredChunkSize, and then the last chunk gets flushed to
     * underlying stream. If flushAll is true and there is no data in a buffer
     * at all then an empty chunk (containing a header only) gets flushed to
     * underlying stream.
     */
     private void flush(boolean flushAll) {
        if (spaceInCurrentChunk == 0) {
            /* flush a completed chunk to underlying stream */
            out.write(buf, 0, preferredChunkGrossSize);
            out.flush();
            reset();
        } else if (flushAll){
            /* complete the last chunk and flush it to underlying stream */
            if (size > 0){
                /* adjust a header start index in case the header of the last
                 * chunk is shorter then preferedHeaderSize */

                int adjustedHeaderStartIndex = preferedHeaderSize -
                        getHeaderSize(size);

                /* write header */
                System.arraycopy(getHeader(size), 0, buf,
                        adjustedHeaderStartIndex, getHeaderSize(size));

                /* write footer */
                buf[count++] = FOOTER[0];
                buf[count++] = FOOTER[1];

                //send the last chunk to underlying stream
                out.write(buf, adjustedHeaderStartIndex, count - adjustedHeaderStartIndex);
            } else {
                //send an empty chunk (containing just a header) to underlying stream
                out.write(EMPTY_CHUNK_HEADER, 0, EMPTY_CHUNK_HEADER_SIZE);
            }

            out.flush();
            reset();
         }
    }

    @Override
    public boolean checkError() {
        return out.checkError();
    }

    /* Check that the output stream is still open */
    private void ensureOpen() {
        if (out == null)
            setError();
    }

   /*
    * Writes data from b[] to an internal buffer and stores the data as data
    * chunks of a following format: {Data length in Hex}{CRLF}{data}{CRLF}
    * The size of the data is preferredChunkSize. As soon as a completed chunk
    * is read from b[] a process of reading from b[] suspends, the chunk gets
    * flushed to the underlying stream and then the reading process from b[]
    * continues. When there is no more sufficient data in b[] to build up a
    * chunk of preferredChunkSize size the data get stored as an incomplete
    * chunk of a following format: {space for data length}{CRLF}{data}
    * The size of the data is of course smaller than preferredChunkSize.
    */
    @Override
    public synchronized void write(byte b[], int off, int len) {
        ensureOpen();
        if ((off < 0) || (off > b.length) || (len < 0) ||
            ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        /* if b[] contains enough data then one loop cycle creates one complete
         * data chunk with a header, body and a footer, and then flushes the
         * chunk to the underlying stream. Otherwise, the last loop cycle
         * creates incomplete data chunk with empty header and with no footer
         * and stores this incomplete chunk in an internal buffer buf[]
         */
        int bytesToWrite = len;
        int inputIndex = off;  /* the index of the byte[] currently being written */

        do {
            /* enough data to complete a chunk */
            if (bytesToWrite >= spaceInCurrentChunk) {

                /* header */
                for (int i=0; i<completeHeader.length; i++)
                    buf[i] = completeHeader[i];

                /* data */
                System.arraycopy(b, inputIndex, buf, count, spaceInCurrentChunk);
                inputIndex += spaceInCurrentChunk;
                bytesToWrite -= spaceInCurrentChunk;
                count += spaceInCurrentChunk;

                /* footer */
                buf[count++] = FOOTER[0];
                buf[count++] = FOOTER[1];
                spaceInCurrentChunk = 0; //chunk is complete

                flush(false);
                if (checkError()){
                    break;
                }
            }

            /* not enough data to build a chunk */
            else {
                /* header */
                /* do not write header if not enough bytes to build a chunk yet */

                /* data */
                System.arraycopy(b, inputIndex, buf, count, bytesToWrite);
                count += bytesToWrite;
                size += bytesToWrite;
                spaceInCurrentChunk -= bytesToWrite;
                bytesToWrite = 0;

                /* footer */
                /* do not write header if not enough bytes to build a chunk yet */
            }
        } while (bytesToWrite > 0);
    }

    @Override
    public synchronized void write(int _b) {
        byte b[] = {(byte)_b};
        write(b, 0, 1);
    }

    public synchronized void reset() {
        count = preferedHeaderSize;
        size = 0;
        spaceInCurrentChunk = preferredChunkDataSize;
    }

    public int size() {
        return size;
    }

    @Override
    public synchronized void close() {
        ensureOpen();

        /* if we have buffer a chunked send it */
        if (size > 0) {
            flush(true);
        }

        /* send a zero length chunk */
        flush(true);

        /* don't close the underlying stream */
        out = null;
    }

    @Override
    public synchronized void flush() {
        ensureOpen();
        if (size > 0) {
            flush(true);
        }
    }
}
