1 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 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 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 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 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 charset) { 69 if(bufferList==null || handler==null) 70 throw new IllegalArgumentException ("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 (); 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(); lookingForLineFeed = false; 116 } 117 break; 118 } } 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 return count; 131 } 132 133 public synchronized void close() throws IOException { 134 if(handler.getSocketChannel()!=null) handler.getSocketChannel().close(); 135 } 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 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 ie) { 194 logger.warning("InterruptedException: "+ie); 195 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(); 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 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 er) { 287 logger.warning("Error while returning ByteBuffer to pool: "+er); 288 } 289 } 290 291 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 } 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 371 public synchronized String readLine() throws IOException { 372 if(index==-1) { 373 while(isLineReady()==false) { 374 try { 375 wait(); 376 } catch(InterruptedException 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 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 e) { 417 logger.fine("["+c+"] Error : "+e); 418 } 419 } 420 } 421 logger.fine("End of dump.."); 422 } 423 } 424 | Popular Tags |