KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > maverick > util > DynamicBuffer


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.maverick.util;
21
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.InterruptedIOException JavaDoc;
25 import java.io.OutputStream JavaDoc;
26
27 /**
28  * <p>
29  * This class provides an alternative method of storing data, used within the
30  * API where Piped Streams could have been used. We found that Piped streams
31  * would lock if a thread attempted to read to data when the OutputStream attached
32  * was not being read; since we have no control over when the user will actually
33  * read the data, this behaviour led us to develop this dynamic buffer which
34  * will automatically grow if the buffer is full.
35  * </p>
36  * *
37  * @author Lee David Painter
38  */

39 public class DynamicBuffer {
40
41   /** Buffer size when the dynamic buffer is opened */
42   protected static final int DEFAULT_BUFFER_SIZE = 32768;
43
44   /** The buffer */
45   protected byte[] buf;
46
47   /** The current write position */
48   protected int writepos = 0;
49
50   /** The current read position */
51   protected int readpos = 0;
52
53   /** This buffers InputStream */
54   protected InputStream JavaDoc in;
55
56   /** This buffers OutputStream */
57   protected OutputStream JavaDoc out;
58   private boolean closed = false;
59   private int interrupt = 5000;
60
61   /**
62    * Creates a new DynamicBuffer object.
63    */

64   public DynamicBuffer() {
65     buf = new byte[DEFAULT_BUFFER_SIZE];
66     in = new DynamicBufferInputStream();
67     out = new DynamicBufferOutputStream();
68   }
69
70   /**
71    * Get the InputStream of this buffer. Use the stream to read data from
72    * this buffer.
73    *
74    * @return
75    */

76   public InputStream JavaDoc getInputStream() {
77     return in;
78   }
79
80   /**
81    * Get the OutputStream of the buffer. Use this stream to write data to
82    * the buffer.
83    *
84    * @return
85    */

86   public OutputStream JavaDoc getOutputStream() {
87     return out;
88   }
89
90   private synchronized void verifyBufferSize(int count) {
91     // If there is not enough data in the buffer, then first attempt to
92
// move the unread data back to the beginning
93
if (count > (buf.length - writepos)) {
94       System.arraycopy(buf, readpos, buf, 0, writepos - readpos);
95       writepos -= readpos;
96       readpos = 0;
97     }
98
99     // Now double check and increase the buffer size if necersary
100
if (count > (buf.length - writepos)) {
101       byte[] tmp = new byte[buf.length + DEFAULT_BUFFER_SIZE];
102       System.arraycopy(buf, 0, tmp, 0, writepos - readpos);
103       buf = tmp;
104     }
105   }
106
107   /**
108    * Return the number of bytes of data available to be read from the buffer
109    * @return
110    */

111   protected synchronized int available() {
112     return writepos - readpos > 0
113         ? writepos - readpos
114         : (closed ? -1 : 0);
115   }
116
117   private synchronized void block() throws InterruptedException JavaDoc {
118
119     // Block and wait for more data
120
if (!closed) {
121       while ( (readpos >= writepos) && !closed) {
122         wait(interrupt);
123       }
124     }
125   }
126
127   /**
128    * Closes the buffer
129    */

130   public synchronized void close() {
131     if (!closed) {
132       closed = true;
133       notifyAll();
134     }
135   }
136
137   /**
138    * Write a byte array to the buffer
139    *
140    * @param b
141    *
142    * @throws IOException
143    */

144   protected synchronized void write(int b) throws IOException JavaDoc {
145     if (closed) {
146       throw new IOException JavaDoc("The buffer is closed");
147     }
148
149     verifyBufferSize(1);
150     buf[writepos] = (byte) b;
151     writepos++;
152
153     notifyAll();
154   }
155
156   /**
157    *
158    *
159    * @param data
160    * @param offset
161    * @param len
162    *
163    * @throws IOException
164    */

165   protected synchronized void write(byte[] data, int offset, int len) throws
166       IOException JavaDoc {
167
168     if (closed) {
169       throw new IOException JavaDoc("The buffer is closed");
170     }
171
172     verifyBufferSize(len);
173     System.arraycopy(data, offset, buf, writepos, len);
174     writepos += len;
175
176     notifyAll();
177   }
178
179   public void setBlockInterrupt(int interrupt) {
180     this.interrupt = interrupt;
181   }
182
183   /**
184    * Read a byte from the buffer
185    *
186    * @return
187    *
188    * @throws IOException
189    * @throws InterruptedIOException
190    */

191   protected synchronized int read() throws IOException JavaDoc {
192     try {
193       block();
194     }
195     catch (InterruptedException JavaDoc ex) {
196       throw new InterruptedIOException JavaDoc(
197           "The blocking operation was interrupted");
198     }
199
200     if (closed && available() <= 0) {
201       return -1;
202     }
203
204     return (int) buf[readpos++];
205
206   }
207
208   /**
209    * Read a byte array from the buffer
210    *
211    * @param data
212    * @param offset
213    * @param len
214    *
215    * @return
216    *
217    * @throws IOException
218    * @throws InterruptedIOException
219    */

220   protected synchronized int read(byte[] data, int offset, int len) throws
221       IOException JavaDoc {
222     try {
223
224       block();
225     }
226     catch (InterruptedException JavaDoc ex) {
227       throw new InterruptedIOException JavaDoc(
228           "The blocking operation was interrupted");
229     }
230
231     if (closed && available() <= 0) {
232       return -1;
233     }
234
235     int read = (len > (writepos - readpos)) ? (writepos - readpos) : len;
236     System.arraycopy(buf, readpos, data, offset, read);
237     readpos += read;
238
239     return read;
240
241   }
242
243   /**
244    * Flush data
245    *
246    * @throws IOException
247    */

248   protected synchronized void flush() throws IOException JavaDoc {
249     notifyAll();
250   }
251
252   class DynamicBufferInputStream
253       extends InputStream JavaDoc {
254     public int read() throws IOException JavaDoc {
255       return DynamicBuffer.this.read();
256     }
257
258     public int read(byte[] data, int offset, int len) throws IOException JavaDoc {
259       return DynamicBuffer.this.read(data, offset, len);
260     }
261
262     public int available() {
263       return DynamicBuffer.this.available();
264     }
265
266     public void close() {
267       DynamicBuffer.this.close();
268     }
269   }
270
271   class DynamicBufferOutputStream
272       extends OutputStream JavaDoc {
273     public void write(int b) throws IOException JavaDoc {
274       DynamicBuffer.this.write(b);
275     }
276
277     public void write(byte[] data, int offset, int len) throws IOException JavaDoc {
278       DynamicBuffer.this.write(data, offset, len);
279     }
280
281     public void flush() throws IOException JavaDoc {
282       DynamicBuffer.this.flush();
283     }
284
285     public void close() {
286       DynamicBuffer.this.close();
287     }
288   }
289 }
290
Popular Tags