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 }