/core/fr.opensagres.xdocreport.core/src/main/java/fr/opensagres/xdocreport/core/io/internal/ByteArrayOutputStream.java
Java | 360 lines | 182 code | 26 blank | 152 comment | 28 complexity | 26ffffdbd45c620d55e226c629135e73 MD5 | raw file
- /**
- * Copyright (C) 2011 Angelo Zerr <angelo.zerr@gmail.com> and Pascal Leclercq <pascal.leclercq@gmail.com>
- *
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- package fr.opensagres.xdocreport.core.io.internal;
- /*
- * 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.
- */
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.UnsupportedEncodingException;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * This class implements an output stream in which the data is written into a byte array. The buffer automatically grows
- * as data is written to it.
- * <p>
- * The data can be retrieved using <code>toByteArray()</code> and <code>toString()</code>.
- * <p>
- * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in this class can be called after the stream has
- * been closed without generating an <tt>IOException</tt>.
- * <p>
- * This is an alternative implementation of the java.io.ByteArrayOutputStream class. The original implementation only
- * allocates 32 bytes at the beginning. As this class is designed for heavy duty it starts at 1024 bytes. In contrast to
- * the original it doesn't reallocate the whole memory block but allocates additional buffers. This way no buffers need
- * to be garbage collected and the contents don't have to be copied to the new buffer. This class is designed to behave
- * exactly like the original. The only exception is the deprecated toString(int) method that has been ignored.
- *
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @author Holger Hoffstatte
- * @version $Id: ByteArrayOutputStream.java 610010 2008-01-08 14:50:59Z niallp $
- */
- public class ByteArrayOutputStream
- extends OutputStream
- {
- /** A singleton empty byte array. */
- private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
- /** The list of buffers, which grows and never reduces. */
- private List<byte[]> buffers = new ArrayList<byte[]>();
- /** The index of the current buffer. */
- private int currentBufferIndex;
- /** The total count of bytes in all the filled buffers. */
- private int filledBufferSum;
- /** The current buffer. */
- private byte[] currentBuffer;
- /** The total count of bytes written. */
- private int count;
- /**
- * Creates a new byte array output stream. The buffer capacity is initially 1024 bytes, though its size increases if
- * necessary.
- */
- public ByteArrayOutputStream()
- {
- this( 1024 );
- }
- /**
- * Creates a new byte array output stream, with a buffer capacity of the specified size, in bytes.
- *
- * @param size the initial size
- * @throws IllegalArgumentException if size is negative
- */
- public ByteArrayOutputStream( int size )
- {
- if ( size < 0 )
- {
- throw new IllegalArgumentException( "Negative initial size: " + size );
- }
- needNewBuffer( size );
- }
- /**
- * Return the appropriate <code>byte[]</code> buffer specified by index.
- *
- * @param index the index of the buffer required
- * @return the buffer
- */
- private byte[] getBuffer( int index )
- {
- return (byte[]) buffers.get( index );
- }
- /**
- * Makes a new buffer available either by allocating a new one or re-cycling an existing one.
- *
- * @param newcount the size of the buffer if one is created
- */
- private void needNewBuffer( int newcount )
- {
- if ( currentBufferIndex < buffers.size() - 1 )
- {
- // Recycling old buffer
- filledBufferSum += currentBuffer.length;
- currentBufferIndex++;
- currentBuffer = getBuffer( currentBufferIndex );
- }
- else
- {
- // Creating new buffer
- int newBufferSize;
- if ( currentBuffer == null )
- {
- newBufferSize = newcount;
- filledBufferSum = 0;
- }
- else
- {
- newBufferSize = Math.max( currentBuffer.length << 1, newcount - filledBufferSum );
- filledBufferSum += currentBuffer.length;
- }
- currentBufferIndex++;
- currentBuffer = new byte[newBufferSize];
- buffers.add( currentBuffer );
- }
- }
- /**
- * Write the bytes to byte array.
- *
- * @param b the bytes to write
- * @param off The start offset
- * @param len The number of bytes to write
- */
- public void write( byte[] b, int off, int len )
- {
- if ( ( off < 0 ) || ( off > b.length ) || ( len < 0 ) || ( ( off + len ) > b.length ) || ( ( off + len ) < 0 ) )
- {
- throw new IndexOutOfBoundsException();
- }
- else if ( len == 0 )
- {
- return;
- }
- synchronized ( this )
- {
- int newcount = count + len;
- int remaining = len;
- int inBufferPos = count - filledBufferSum;
- while ( remaining > 0 )
- {
- int part = Math.min( remaining, currentBuffer.length - inBufferPos );
- System.arraycopy( b, off + len - remaining, currentBuffer, inBufferPos, part );
- remaining -= part;
- if ( remaining > 0 )
- {
- needNewBuffer( newcount );
- inBufferPos = 0;
- }
- }
- count = newcount;
- }
- }
- /**
- * Write a byte to byte array.
- *
- * @param b the byte to write
- */
- public synchronized void write( int b )
- {
- int inBufferPos = count - filledBufferSum;
- if ( inBufferPos == currentBuffer.length )
- {
- needNewBuffer( count + 1 );
- inBufferPos = 0;
- }
- currentBuffer[inBufferPos] = (byte) b;
- count++;
- }
- /**
- * Writes the entire contents of the specified input stream to this byte stream. Bytes from the input stream are
- * read directly into the internal buffers of this streams.
- *
- * @param in the input stream to read from
- * @return total number of bytes read from the input stream (and written to this stream)
- * @throws IOException if an I/O error occurs while reading the input stream
- * @since Commons IO 1.4
- */
- public synchronized int write( InputStream in )
- throws IOException
- {
- int readCount = 0;
- int inBufferPos = count - filledBufferSum;
- int n = in.read( currentBuffer, inBufferPos, currentBuffer.length - inBufferPos );
- while ( n != -1 )
- {
- readCount += n;
- inBufferPos += n;
- count += n;
- if ( inBufferPos == currentBuffer.length )
- {
- needNewBuffer( currentBuffer.length );
- inBufferPos = 0;
- }
- n = in.read( currentBuffer, inBufferPos, currentBuffer.length - inBufferPos );
- }
- return readCount;
- }
- /**
- * Return the current size of the byte array.
- *
- * @return the current size of the byte array
- */
- public synchronized int size()
- {
- return count;
- }
- /**
- * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in this class can be called after the stream
- * has been closed without generating an <tt>IOException</tt>.
- *
- * @throws IOException never (this method should not declare this exception but it has to now due to backwards
- * compatability)
- */
- public void close()
- throws IOException
- {
- // nop
- }
- /**
- * @see java.io.ByteArrayOutputStream#reset()
- */
- public synchronized void reset()
- {
- count = 0;
- filledBufferSum = 0;
- currentBufferIndex = 0;
- currentBuffer = getBuffer( currentBufferIndex );
- }
- /**
- * Writes the entire contents of this byte stream to the specified output stream.
- *
- * @param out the output stream to write to
- * @throws IOException if an I/O error occurs, such as if the stream is closed
- * @see java.io.ByteArrayOutputStream#writeTo(OutputStream)
- */
- public synchronized void writeTo( OutputStream out )
- throws IOException
- {
- int remaining = count;
- for ( int i = 0; i < buffers.size(); i++ )
- {
- byte[] buf = getBuffer( i );
- int c = Math.min( buf.length, remaining );
- out.write( buf, 0, c );
- remaining -= c;
- if ( remaining == 0 )
- {
- break;
- }
- }
- }
- /**
- * Gets the curent contents of this byte stream as a byte array. The result is independent of this stream.
- *
- * @return the current contents of this output stream, as a byte array
- * @see java.io.ByteArrayOutputStream#toByteArray()
- */
- public synchronized byte[] toByteArray()
- {
- int remaining = count;
- if ( remaining == 0 )
- {
- return EMPTY_BYTE_ARRAY;
- }
- byte newbuf[] = new byte[remaining];
- int pos = 0;
- for ( int i = 0; i < buffers.size(); i++ )
- {
- byte[] buf = getBuffer( i );
- int c = Math.min( buf.length, remaining );
- System.arraycopy( buf, 0, newbuf, pos, c );
- pos += c;
- remaining -= c;
- if ( remaining == 0 )
- {
- break;
- }
- }
- return newbuf;
- }
- /**
- * Gets the curent contents of this byte stream as a string.
- *
- * @return the contents of the byte array as a String
- * @see java.io.ByteArrayOutputStream#toString()
- */
- public String toString()
- {
- return new String( toByteArray() );
- }
- /**
- * Gets the curent contents of this byte stream as a string using the specified encoding.
- *
- * @param enc the name of the character encoding
- * @return the string converted from the byte array
- * @throws UnsupportedEncodingException if the encoding is not supported
- * @see java.io.ByteArrayOutputStream#toString(String)
- */
- public String toString( String enc )
- throws UnsupportedEncodingException
- {
- return new String( toByteArray(), enc );
- }
- }