KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quickserver > util > io > ByteBufferInputStream


1 /*
2  * This file is part of the QuickServer library
3  * Copyright (C) QuickServer.org
4  *
5  * Use, modification, copying and distribution of this software is subject to
6  * the terms and conditions of the GNU Lesser General Public License.
7  * You should have received a copy of the GNU LGP License along with this
8  * library; if not, you can download a copy from <http://www.quickserver.org/>.
9  *
10  * For questions, suggestions, bug-reports, enhancement-requests etc.
11  * visit http://www.quickserver.org
12  *
13  */

14
15 package org.quickserver.util.io;
16
17 import java.io.*;
18 import java.nio.*;
19 import java.nio.charset.*;
20 import java.util.*;
21 import org.apache.commons.pool.ObjectPool;
22 import org.quickserver.net.server.ClientHandler;
23 import java.util.logging.*;
24 import org.quickserver.util.*;
25
26 /**
27  * This is an InputStream constructed from list of ByteBuffers. This is
28  * used in non-blocking mode.
29  * @since 1.4.5
30  * @author Akshathkumar Shetty
31  */

32 public class ByteBufferInputStream extends InputStream {
33     private static Logger logger = Logger.getLogger(ByteBufferInputStream.class.getName());
34     static {
35         logger.setLevel(Level.INFO);
36     }
37
38     /**
39      * Sets the debug flag.
40      */

41     public static void setDebug(boolean flag) {
42         if(flag)
43             logger.setLevel(Level.FINEST);
44         else
45             logger.setLevel(Level.INFO);
46     }
47
48     /**
49      * @since 1.4.7
50      */

51     public static boolean isLoggable(Level level) {
52         return logger.isLoggable(level);
53     }
54
55
56     private ArrayList bufferList;
57     private ClientHandler handler;
58
59     private CharsetDecoder decoder;
60     private CharsetEncoder encoder;
61     private StringBuffer JavaDoc strings;
62
63     private int pos = 0;
64     private int index = -1;
65     private int start = 0;
66     private boolean lookingForLineFeed = false;
67
68     public ByteBufferInputStream(ArrayList bufferList, ClientHandler handler, String JavaDoc charset) {
69         if(bufferList==null || handler==null)
70             throw new IllegalArgumentException JavaDoc("ArrayList or ClientHandler was null.");
71         this.bufferList = bufferList;
72         this.handler = handler;
73         Charset _charset = Charset.forName(charset);
74         decoder = _charset.newDecoder();
75         encoder = _charset.newEncoder();
76         strings = new StringBuffer JavaDoc();
77     }
78
79     public synchronized int availableOnlyInByteBuffer() {
80         int count = 0;
81         ByteBuffer byteBuffer = null;
82         int size = bufferList.size();
83         for(int c=0;c<size;c++) {
84             byteBuffer = (ByteBuffer)bufferList.get(c);
85             count += byteBuffer.remaining();
86         }
87         logger.finest("count: "+count);
88         return count;
89     }
90
91     public synchronized int available() {
92         int count = 0;
93         ByteBuffer byteBuffer = null;
94
95         if(lookingForLineFeed) {
96             char c = '\0';
97             if(strings.length()!=0) {
98                 c = strings.charAt(0);
99                 if(c=='\n') {
100                     strings.deleteCharAt(0);
101                     lookingForLineFeed = false;
102                 }
103             } else {
104                 while(bufferList.size()!=0) {
105                     byteBuffer = (ByteBuffer)bufferList.get(0);
106                     if(byteBuffer.remaining()==0) {
107                         returnBufferBack();
108                         continue;
109                     }
110                     
111                     int p = byteBuffer.position();
112                     c = (char) byteBuffer.get(p);
113                     if(c=='\n') {
114                         byteBuffer.get();//move position
115
lookingForLineFeed = false;
116                     }
117                     break;
118                 }//end of while
119
}
120         }
121         count += strings.length();
122         
123         
124         int size = bufferList.size();
125         for(int c=0;c<size;c++) {
126             byteBuffer = (ByteBuffer)bufferList.get(c);
127             count += byteBuffer.remaining();
128         }
129         //logger.finest("count: "+count);
130
return count;
131     }
132
133     public synchronized void close() throws IOException {
134         if(handler.getSocketChannel()!=null) handler.getSocketChannel().close();
135         //handler.closeConnection();
136
}
137
138     public boolean markSupported() {
139         return false;
140     }
141
142     public synchronized int read() throws IOException {
143         handler.isConnected();
144         if(strings.length()!=0) {
145             addStringsBackAsBuffer();
146         }
147
148         if(bufferList.size()==0) {
149             try {
150                 wait();
151             } catch(InterruptedException JavaDoc ie) {
152                 logger.warning("InterruptedException: "+ie);
153                 return -1;
154             }
155             if(bufferList.size()==0) return -1;
156         }
157         ByteBuffer byteBuffer = null;
158         while(bufferList.size()!=0) {
159             byteBuffer = (ByteBuffer)bufferList.get(0);
160             if(byteBuffer.remaining()==0) {
161                 returnBufferBack();
162                 continue;
163             }
164
165             if(lookingForLineFeed) {
166                 int lflfChar = (int) byteBuffer.get();
167                 lookingForLineFeed = false;
168                 if(lflfChar==(int)'\n') {
169                     continue;
170                 } else {
171                     return lflfChar;
172                 }
173             } else {
174                 return (int) byteBuffer.get();
175             }
176         }
177         return read();
178     }
179
180     public int read(byte[] b) throws IOException {
181         return read(b, 0, b.length);
182     }
183
184     public synchronized int read(byte[] b, int off, int len) throws IOException {
185         handler.isConnected();
186         if(strings.length()!=0) {
187             addStringsBackAsBuffer();
188         }
189
190         if(bufferList.size()==0) {
191             try {
192                 wait();
193             } catch(InterruptedException JavaDoc ie) {
194                 logger.warning("InterruptedException: "+ie);
195                 //ie.printStackTrace();
196
return -1;
197             }
198             if(bufferList.size()==0) return -1;
199         }
200         ByteBuffer byteBuffer = null;
201         int read = 0;
202         int remaining = 0;
203         int toRead = len;
204         do {
205             byteBuffer = (ByteBuffer) bufferList.get(0);
206             remaining = byteBuffer.remaining();
207
208             if(remaining==0) {
209                 returnBufferBack();
210                 continue;
211             }
212
213             if(lookingForLineFeed) {
214                 int p = byteBuffer.position();
215                 byte lflfChar = byteBuffer.get(p);
216                 lookingForLineFeed = false;
217
218                 if(lflfChar==(byte)'\n') {
219                     byteBuffer.get();//move position
220
continue;
221                 }
222             }
223
224             if(remaining < toRead) {
225                 byteBuffer.get(b, off, remaining);
226                 off = off + remaining;
227
228                 read = read + remaining;
229                 toRead = toRead - remaining;
230             } else {
231                 byteBuffer.get(b, off, toRead);
232                 read = read + toRead;
233                 return read;
234             }
235         } while(bufferList.size()!=0);
236         return read;
237     }
238
239     public long skip(long n) throws IOException {
240         if(n<0) return 0;
241         int s=0;
242         for(;s<n;s++) {
243             if(read()==-1) break;
244         }
245         return s;
246     }
247
248     private void addStringsBackAsBuffer() {
249         try {
250             ByteBuffer borrowBuffer = null;
251             ByteBuffer bb = encoder.encode(CharBuffer.wrap(strings));
252             strings.setLength(0);
253             do {
254                 if(borrowBuffer==null) {
255                     borrowBuffer = (ByteBuffer) handler.getServer().getByteBufferPool().borrowObject();
256                 }
257
258                 borrowBuffer.put(bb.get());
259
260                 if(borrowBuffer.hasRemaining()==false) {
261                     borrowBuffer.flip();
262                     bufferList.add(0, borrowBuffer);
263                     borrowBuffer = null;
264                 }
265             } while(bb.hasRemaining());
266
267             if(borrowBuffer!=null) {
268                 borrowBuffer.flip();
269                 bufferList.add(0, borrowBuffer);
270             }
271         } catch(Exception JavaDoc er) {
272             logger.warning("Error : "+er);
273         }
274         start = 0;
275         index = -1;
276         pos = 0;
277     }
278
279     private void returnBufferBack() {
280         returnBufferBack((ByteBuffer)bufferList.remove(0));
281     }
282
283     private void returnBufferBack(ByteBuffer byteBuffer) {
284         try {
285             handler.getServer().getByteBufferPool().returnObject(byteBuffer);
286         } catch(Exception JavaDoc er) {
287             logger.warning("Error while returning ByteBuffer to pool: "+er);
288         }
289     }
290
291     //-- extra helpers
292
/**
293      * Checks if a line of String is ready to be read.
294      * @throws IOException if connection is lost or closed.
295      */

296     public synchronized boolean isLineReady() throws IOException {
297         handler.isConnected();
298         boolean result = false;
299
300         result = isLineReadyForStringBuffer();
301
302         if(result==true || bufferList.size()==0) {
303             if(logger.isLoggable(Level.FINEST))
304                 logger.finest("result: "+result);
305             return result;
306         }
307
308         ByteBuffer byteBuffer = null;
309         CharBuffer charBuffer = null;
310         
311         while(result==false && bufferList.size()!=0) {
312             byteBuffer = (ByteBuffer)bufferList.get(0);
313             if(byteBuffer.remaining()==0) {
314                 returnBufferBack();
315                 continue;
316             }
317             charBuffer = decoder.decode(byteBuffer);
318             if(charBuffer==null) {
319                 returnBufferBack();
320                 continue;
321             }
322
323             strings.append(charBuffer);
324             returnBufferBack();
325
326             result = isLineReadyForStringBuffer();
327         }//end of while
328

329         if(logger.isLoggable(Level.FINEST))
330             logger.finest("result: "+result);
331         return result;
332     }
333
334     private boolean isLineReadyForStringBuffer() {
335         if(index!=-1) return true;
336
337         int stringsLength = strings.length();
338
339         while(pos < stringsLength) {
340             char c = strings.charAt(pos);
341
342             if(c=='\n') {
343                 if(lookingForLineFeed) {
344                     strings.deleteCharAt(0);
345                     stringsLength--;
346                     lookingForLineFeed = false;
347                     continue;
348                 } else {
349                     index = pos;
350                     pos++;
351                     return true;
352                 }
353             } if(c=='\r') {
354                 index = pos;
355                 lookingForLineFeed = true;
356                 pos++;
357                 return true;
358             } else {
359                 pos++;
360                 lookingForLineFeed = false;
361             }
362         }
363         return false;
364     }
365
366     /**
367      * Reads a line of String if ready. If line is not yet ready this will
368      * block. To find out if the line is ready use <code>isLineReady()</code>
369      * @see #isLineReady()
370      */

371     public synchronized String JavaDoc readLine() throws IOException {
372         if(index==-1) {
373             while(isLineReady()==false) {
374                 try {
375                     wait();
376                 } catch(InterruptedException JavaDoc ie) {
377                     logger.warning("InterruptedException: "+ie);
378                     return null;
379                 }
380             }
381         }
382
383         int stringsLength = strings.length();
384
385         Assertion.affirm(index <= stringsLength);
386         String JavaDoc data = strings.substring(start,index);
387         
388         if(pos < stringsLength)
389             strings.delete(0, pos);
390         else
391             strings.setLength(0);
392
393         start = 0;
394         pos = start;
395         index = -1;
396         return data;
397     }
398
399     public void dumpContent() {
400         if(logger.isLoggable(Level.FINE)==false) {
401             logger.warning("Can't precede. Logging level FINE is not luggable! ");
402             return;
403         }
404
405         logger.fine("Start of dump..");
406         synchronized(bufferList) {
407             int size = bufferList.size();
408             ByteBuffer byteBuffer = null;
409             if(strings.length()!=0) {
410                 logger.fine("[decoded] "+strings);
411             }
412             for(int c=0;c<size;c++) {
413                 byteBuffer = (ByteBuffer)bufferList.get(c);
414                 try {
415                     logger.fine("["+c+"] "+decoder.decode(byteBuffer.duplicate()));
416                 } catch(Exception JavaDoc e) {
417                     logger.fine("["+c+"] Error : "+e);
418                 }
419             }
420         }
421         logger.fine("End of dump..");
422     }
423 }
424
Popular Tags