Frames | No Frames |
1: /** 2: * ======================================== 3: * JFreeReport : a free Java report library 4: * ======================================== 5: * 6: * Project Info: http://reporting.pentaho.org/ 7: * 8: * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors. 9: * 10: * This library is free software; you can redistribute it and/or modify it under the terms 11: * of the GNU Lesser General Public License as published by the Free Software Foundation; 12: * either version 2.1 of the License, or (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 15: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16: * See the GNU Lesser General Public License for more details. 17: * 18: * You should have received a copy of the GNU Lesser General Public License along with this 19: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 20: * Boston, MA 02111-1307, USA. 21: * 22: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 23: * in the United States and other countries.] 24: * 25: * ------------ 26: * $Id: MemoryByteArrayOutputStream.java 3525 2007-10-16 11:43:48Z tmorgner $ 27: * ------------ 28: * (C) Copyright 2000-2005, by Object Refinery Limited. 29: * (C) Copyright 2005-2007, by Pentaho Corporation. 30: */ 31: 32: package org.jfree.report.util; 33: 34: import java.io.IOException; 35: import java.io.OutputStream; 36: 37: import org.jfree.util.Log; 38: 39: /** 40: * A string writer that is able to write large amounts of data. The original StringWriter contained in Java doubles 41: * its buffersize everytime the buffer overflows. This is nice with small amounts of data, but awfull for huge 42: * buffers. 43: * 44: * @author Thomas Morgner 45: */ 46: public class MemoryByteArrayOutputStream extends OutputStream 47: { 48: private int initialBufferSize; 49: private int maximumBufferIncrement; 50: private int cursor; 51: private byte[] buffer; 52: private byte[] singleIntArray; 53: 54: /** 55: * Create a new character-stream writer whose critical sections will synchronize on the writer itself. 56: */ 57: public MemoryByteArrayOutputStream() 58: { 59: this(4096, 65536); 60: } 61: 62: /** 63: * Create a new character-stream writer whose critical sections will synchronize on the writer itself. 64: */ 65: public MemoryByteArrayOutputStream(final int bufferSize, final int maximumBufferIncrement) 66: { 67: this.initialBufferSize = bufferSize; 68: this.maximumBufferIncrement = maximumBufferIncrement; 69: this.buffer = new byte[bufferSize]; 70: this.singleIntArray = new byte[1]; 71: } 72: 73: 74: /** 75: * Write a portion of an array of characters. 76: * 77: * @param cbuf Array of characters 78: * @param off Offset from which to start writing characters 79: * @param len Number of characters to write 80: * @throws java.io.IOException If an I/O error occurs 81: */ 82: public synchronized void write(final byte[] cbuf, final int off, final int len) throws IOException 83: { 84: if (len < 0) 85: { 86: throw new IllegalArgumentException(); 87: } 88: if (off < 0) 89: { 90: throw new IndexOutOfBoundsException(); 91: } 92: if (cbuf == null) 93: { 94: throw new NullPointerException(); 95: } 96: if ((len + off) > cbuf.length) 97: { 98: throw new IndexOutOfBoundsException(); 99: } 100: 101: ensureSize (cursor + len); 102: 103: System.arraycopy(cbuf, off, this.buffer, cursor, len); 104: cursor += len; 105: } 106: 107: /** 108: * Writes <code>b.length</code> bytes from the specified byte array to this output stream. The general contract for 109: * <code>write(b)</code> is that it should have exactly the same effect as the call <code>write(b, 0, 110: * b.length)</code>. 111: * 112: * @param b the data. 113: * @throws java.io.IOException if an I/O error occurs. 114: * @see java.io.OutputStream#write(byte[], int, int) 115: */ 116: public void write(final byte[] b) throws IOException 117: { 118: write(b, 0, b.length); 119: } 120: 121: /** 122: * Writes the specified byte to this output stream. The general contract for <code>write</code> is that one byte is 123: * written to the output stream. The byte to be written is the eight low-order bits of the argument <code>b</code>. 124: * The 24 high-order bits of <code>b</code> are ignored. 125: * <p/> 126: * Subclasses of <code>OutputStream</code> must provide an implementation for this method. 127: * 128: * @param b the <code>byte</code>. 129: * @throws java.io.IOException if an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the 130: * output stream has been closed. 131: */ 132: public synchronized void write(final int b) throws IOException 133: { 134: this.singleIntArray[0] = (byte) (0xFF & b); 135: write(singleIntArray, 0, 1); 136: } 137: 138: private void ensureSize(final int size) 139: { 140: if (this.buffer.length >= size) 141: { 142: return; 143: } 144: 145: final int computedSize = (int) Math.min ((this.buffer.length + 1) * 1.5, this.buffer.length + maximumBufferIncrement); 146: final int newSize = Math.max (size, computedSize); 147: final byte[] newBuffer = new byte[newSize]; 148: System.arraycopy(this.buffer, 0, newBuffer, 0, cursor); 149: this.buffer = newBuffer; 150: } 151: 152: /** 153: * Flush the stream. If the stream has saved any characters from the various write() methods in a buffer, write them 154: * immediately to their intended destination. Then, if that destination is another character or byte stream, flush 155: * it. Thus one flush() invocation will flush all the buffers in a chain of Writers and OutputStreams. 156: * <p/> 157: * If the intended destination of this stream is an abstraction provided by the underlying operating system, for 158: * example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to 159: * the operating system for writing; it does not guarantee that they are actually written to a physical device such as 160: * a disk drive. 161: * 162: * @throws java.io.IOException If an I/O error occurs 163: */ 164: public void flush() throws IOException 165: { 166: if ((buffer.length - cursor) > 50000) 167: { 168: Log.debug("WASTED: " + (buffer.length - cursor)); 169: } 170: } 171: 172: /** 173: * Close the stream, flushing it first. Once a stream has been closed, further write() or flush() invocations will 174: * cause an IOException to be thrown. Closing a previously-closed stream, however, has no effect. 175: * 176: * @throws java.io.IOException If an I/O error occurs 177: */ 178: public void close() throws IOException 179: { 180: } 181: 182: public synchronized byte[] toByteArray() 183: { 184: final byte[] retval = new byte[cursor]; 185: System.arraycopy(buffer, 0, retval, 0, cursor); 186: return retval; 187: } 188: 189: public int getLength() 190: { 191: return cursor; 192: } 193: 194: public byte[] getRaw() 195: { 196: if ((buffer.length - cursor) > 50000) 197: { 198: Log.debug("WASTED: " + (buffer.length - cursor) + " Length: " + buffer.length); 199: } 200: return buffer; 201: } 202: }