KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > activemq > transport > nio > NIOOutputStream


1 /**
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one or more
4  * contributor license agreements. See the NOTICE file distributed with
5  * this work for additional information regarding copyright ownership.
6  * The ASF licenses this file to You under the Apache License, Version 2.0
7  * (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package org.apache.activemq.transport.nio;
19
20 import java.io.EOFException JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.InterruptedIOException JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.nio.ByteBuffer JavaDoc;
25 import java.nio.channels.WritableByteChannel JavaDoc;
26
27 /**
28  * An optimized buffered outputstream for Tcp
29  *
30  * @version $Revision: 1.1.1.1 $
31  */

32
33 public class NIOOutputStream extends OutputStream JavaDoc {
34     
35     private final static int BUFFER_SIZE = 8192;
36
37     private final WritableByteChannel JavaDoc out;
38     private final byte[] buffer;
39     private final ByteBuffer JavaDoc byteBuffer;
40     
41     private int count;
42     private boolean closed;
43
44     /**
45      * Constructor
46      *
47      * @param out
48      */

49     public NIOOutputStream(WritableByteChannel JavaDoc out) {
50         this(out, BUFFER_SIZE);
51     }
52
53     /**
54      * Creates a new buffered output stream to write data to the specified underlying output stream with the specified
55      * buffer size.
56      *
57      * @param out the underlying output stream.
58      * @param size the buffer size.
59      * @throws IllegalArgumentException if size <= 0.
60      */

61     public NIOOutputStream(WritableByteChannel JavaDoc out, int size) {
62         this.out = out;
63         if (size <= 0) {
64             throw new IllegalArgumentException JavaDoc("Buffer size <= 0");
65         }
66         buffer = new byte[size];
67         byteBuffer = ByteBuffer.wrap(buffer);
68     }
69
70     /**
71      * write a byte on to the stream
72      *
73      * @param b - byte to write
74      * @throws IOException
75      */

76     public void write(int b) throws IOException JavaDoc {
77         checkClosed();
78         if (availableBufferToWrite() < 1) {
79             flush();
80         }
81         buffer[count++] = (byte) b;
82     }
83
84
85     /**
86      * write a byte array to the stream
87      *
88      * @param b the byte buffer
89      * @param off the offset into the buffer
90      * @param len the length of data to write
91      * @throws IOException
92      */

93     public void write(byte b[], int off, int len) throws IOException JavaDoc {
94         checkClosed();
95         if (availableBufferToWrite() < len) {
96             flush();
97         }
98         if (buffer.length >= len) {
99             System.arraycopy(b, off, buffer, count, len);
100             count += len;
101         }
102         else {
103             write( ByteBuffer.wrap(b, off, len));
104         }
105     }
106
107     /**
108      * flush the data to the output stream
109      * This doesn't call flush on the underlying outputstream, because
110      * Tcp is particularly efficent at doing this itself ....
111      *
112      * @throws IOException
113      */

114     public void flush() throws IOException JavaDoc {
115         if (count > 0 && out != null) {
116             byteBuffer.position(0);
117             byteBuffer.limit(count);
118             write(byteBuffer);
119             count = 0;
120         }
121     }
122
123     /**
124      * close this stream
125      *
126      * @throws IOException
127      */

128     public void close() throws IOException JavaDoc {
129         super.close();
130         closed = true;
131     }
132
133
134     /**
135      * Checks that the stream has not been closed
136      *
137      * @throws IOException
138      */

139     protected void checkClosed() throws IOException JavaDoc {
140         if (closed) {
141             throw new EOFException JavaDoc("Cannot write to the stream any more it has already been closed");
142         }
143     }
144
145     /**
146      * @return the amount free space in the buffer
147      */

148     private int availableBufferToWrite() {
149         return buffer.length - count;
150     }
151     
152     protected void write(ByteBuffer JavaDoc data) throws IOException JavaDoc {
153         int remaining = data.remaining();
154         int lastRemaining = remaining-1;
155         long delay=1;
156         while( remaining > 0 ) {
157             
158             // We may need to do a little bit of sleeping to avoid a busy loop.
159
// Slow down if no data was written out..
160
if( remaining == lastRemaining ) {
161                 try {
162                     // Use exponential rollback to increase sleep time.
163
Thread.sleep(delay);
164                     delay *= 2;
165                     if( delay > 1000 ) {
166                         delay = 1000;
167                     }
168                 } catch (InterruptedException JavaDoc e) {
169                     throw new InterruptedIOException JavaDoc();
170                 }
171             } else {
172                 delay = 1;
173             }
174             lastRemaining = remaining;
175             
176             // Since the write is non-blocking, all the data may not have been written.
177
out.write( data );
178             remaining = data.remaining();
179         }
180     }
181     
182 }
183
Popular Tags