1 /*** 2 * 3 * Copyright 2004 Protique Ltd 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 **/ 18 19 package org.codehaus.activemq.transport.tcp; 20 21 import java.io.EOFException; 22 import java.io.FilterOutputStream; 23 import java.io.IOException; 24 import java.io.OutputStream; 25 26 /*** 27 * An optimized buffered outputstream for Tcp 28 * 29 * @version $Revision: 1.4 $ 30 */ 31 32 public class TcpBufferedOutputStream extends FilterOutputStream { 33 private final static int BUFFER_SIZE = 4096; 34 private byte[] buf; 35 private int count; 36 37 /*** 38 * Constructor 39 * 40 * @param out 41 */ 42 public TcpBufferedOutputStream(OutputStream out) { 43 this(out, BUFFER_SIZE); 44 } 45 46 /*** 47 * Creates a new buffered output stream to write data to the specified underlying output stream with the specified 48 * buffer size. 49 * 50 * @param out the underlying output stream. 51 * @param size the buffer size. 52 * @throws IllegalArgumentException if size <= 0. 53 */ 54 public TcpBufferedOutputStream(OutputStream out, int size) { 55 super(out); 56 if (size <= 0) { 57 throw new IllegalArgumentException("Buffer size <= 0"); 58 } 59 buf = new byte[size]; 60 } 61 62 /*** 63 * write a byte on to the stream 64 * 65 * @param b - byte to write 66 * @throws IOException 67 */ 68 public void write(int b) throws IOException { 69 checkClosed(); 70 if (availableBufferToWrite() < 1) { 71 flush(); 72 } 73 buf[count++] = (byte) b; 74 } 75 76 77 /*** 78 * write a byte array to the stream 79 * 80 * @param b the byte buffer 81 * @param off the offset into the buffer 82 * @param len the length of data to write 83 * @throws IOException 84 */ 85 public void write(byte b[], int off, int len) throws IOException { 86 checkClosed(); 87 if (availableBufferToWrite() < len) { 88 flush(); 89 } 90 if (buf.length >= len) { 91 System.arraycopy(b, off, buf, count, len); 92 count += len; 93 } 94 else { 95 out.write(b, off, len); 96 } 97 } 98 99 /*** 100 * flush the data to the output stream 101 * This doesn't call flush on the underlying outputstream, because 102 * Tcp is particularly efficent at doing this itself .... 103 * 104 * @throws IOException 105 */ 106 public void flush() throws IOException { 107 if (count > 0 && out != null) { 108 out.write(buf, 0, count); 109 count = 0; 110 } 111 } 112 113 /*** 114 * close this stream 115 * 116 * @throws IOException 117 */ 118 public void close() throws IOException { 119 super.close(); 120 out = null; 121 buf = null; 122 } 123 124 125 /*** 126 * Checks that the stream has not been closed 127 * 128 * @throws IOException 129 */ 130 protected void checkClosed() throws IOException { 131 if (buf == null || out == null) { 132 throw new EOFException("Cannot write to the stream any more it has already been closed"); 133 } 134 } 135 136 /*** 137 * @return the amount free space in the buffer 138 */ 139 private int availableBufferToWrite() { 140 return buf.length - count; 141 } 142 }