1 14 15 package org.quickserver.util.io; 16 17 import java.io.*; 18 import java.nio.*; 19 import java.util.*; 20 import org.apache.commons.pool.ObjectPool; 21 import org.quickserver.net.server.ClientHandler; 22 import org.quickserver.net.server.impl.NonBlockingClientHandler; 23 import java.util.logging.*; 24 25 31 public class ByteBufferOutputStream extends OutputStream { 32 private static Logger logger = Logger.getLogger(ByteBufferOutputStream.class.getName()); 33 static { 34 logger.setLevel(Level.INFO); 35 } 36 37 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 private ArrayList bufferList; 56 private ByteBuffer lastByteBuffer = null; 57 private NonBlockingClientHandler handler; 58 private Object toNotify = null; 59 60 64 public ByteBufferOutputStream(ArrayList bufferList, ClientHandler handler) { 65 if(bufferList==null || handler==null) 66 throw new IllegalArgumentException ("ArrayList or ClientHandler was null."); 67 this.bufferList = bufferList; 68 this.handler = (NonBlockingClientHandler) handler; 69 } 70 71 public synchronized void close() { 72 if(lastByteBuffer!=null) { 73 returnBufferBack(lastByteBuffer); 74 } 75 } 76 77 public void flush() throws IOException { 78 if(bufferList.size()!=0 || lastByteBuffer!=null) { 79 handler.registerWrite(); 80 } else { 81 return; 82 } 83 84 while(bufferList.size()>=5) { 85 handler.waitTillFullyWritten(); 86 } 87 } 88 89 public synchronized void write(int b) throws IOException { 90 handler.isConnected(); 91 ByteBuffer byteBuffer = null; 92 if(bufferList.size()!=0) { 93 byteBuffer = (ByteBuffer) bufferList.remove(bufferList.size()-1); 94 if(byteBuffer.remaining()==0) { 95 bufferList.add(byteBuffer); 96 byteBuffer = null; 97 } 98 } 99 try { 100 if(byteBuffer==null) { 101 byteBuffer = (ByteBuffer) handler.getServer().getByteBufferPool().borrowObject(); 102 } 103 } catch(Exception e) { 104 logger.warning("Could not borrow ByteBufer from pool: "+e); 105 throw new IOException(e.toString()); 106 } 107 byteBuffer.put((byte)b); 108 bufferList.add(byteBuffer); 109 } 110 111 public void write(byte[] b) throws IOException { 112 write(b, 0, b.length); 113 } 114 115 public synchronized void write(byte[] b, int off, int len) throws IOException { 116 if(len==0) { 117 return; 118 } 119 120 handler.isConnected(); 121 ByteBuffer byteBuffer = null; 122 int remaining = 0; 123 int toWrite = len; 124 125 if(toWrite!=0 && bufferList.size()!=0) { 126 byteBuffer = (ByteBuffer) bufferList.remove(bufferList.size()-1); 127 if(byteBuffer.remaining()==0) { 128 bufferList.add(byteBuffer); 129 byteBuffer = null; 130 } 131 } 132 133 while(toWrite!=0) { 134 try { 135 if(byteBuffer==null) { 136 byteBuffer = (ByteBuffer) 137 handler.getServer().getByteBufferPool().borrowObject(); 138 } 139 } catch(Exception e) { 140 logger.warning("Could not borrow ByteBufer from pool: "+e); 141 throw new IOException(e.toString()); 142 } 143 144 remaining = byteBuffer.remaining(); 145 if(remaining < toWrite) { 146 byteBuffer.put(b, off, remaining); 147 off = off + remaining; 148 149 toWrite = toWrite - remaining; 150 } else { 151 byteBuffer.put(b, off, toWrite); 152 toWrite=0; 153 } 154 bufferList.add(byteBuffer); 155 byteBuffer = null; 156 } 157 } 158 159 public synchronized boolean writeAllByteBuffer() throws IOException { 161 if(lastByteBuffer!=null) { 162 writeLastByteBuffer(); 163 if(lastByteBuffer!=null) return false; 164 } 165 166 if(bufferList.size()==0) { 167 if(toNotify!=null) { 168 synchronized(toNotify) { 169 toNotify.notify(); 170 toNotify = null; 171 } 172 } 173 return true; 174 } 175 176 while(bufferList.size()!=0) { 177 lastByteBuffer = (ByteBuffer) bufferList.remove(0); 178 lastByteBuffer.flip(); 179 writeLastByteBuffer(); 180 if(lastByteBuffer != null) return false; 181 } 182 183 if(toNotify!=null) { 184 synchronized(toNotify) { 185 toNotify.notify(); 186 toNotify = null; 187 } 188 } 189 return true; 190 } 191 192 private synchronized void writeLastByteBuffer() throws IOException { 193 int written = 0; 194 while(lastByteBuffer.remaining()!=0) { 195 java.nio.channels.SocketChannel sc = handler.getSocketChannel(); 196 if(sc!=null && sc.isOpen()) { 197 written = sc.write(lastByteBuffer); 198 if(written==0) { 199 break; 200 } 201 if(logger.isLoggable(Level.FINEST)) { 202 logger.finest("Written "+written+" bytes"); 203 } 204 } else { 205 throw new IOException("SocketChannel was closed."); 206 } 207 } 208 if(lastByteBuffer.remaining()==0) { 209 returnBufferBack(lastByteBuffer); 210 lastByteBuffer = null; 211 } 212 } 213 214 private void returnBufferBack(ByteBuffer byteBuffer) { 215 try { 216 handler.getServer().getByteBufferPool().returnObject(byteBuffer); 217 } catch(Exception er) { 218 logger.warning("Error while returning ByteBuffer to pool: "+er); 219 } 220 } 221 222 public void forceNotify() { 223 if(toNotify==null) return; 224 synchronized(toNotify) { 225 toNotify.notify(); 226 toNotify = null; 227 } 228 } 229 230 public boolean isDataAvailableForWrite(Object toNotify) { 231 if(lastByteBuffer!=null) { 232 if(this.toNotify!=null) { 233 throw new IllegalStateException ("toNotify object was already set!"); 234 } 235 this.toNotify = toNotify; 236 return true; 237 } 238 if(bufferList.size()==0) { 239 return false; 240 } else { 241 if(this.toNotify!=null) { 242 throw new IllegalStateException ("toNotify object was already set!"); 243 } 244 this.toNotify = toNotify; 245 return true; 246 } 247 } 248 } 249 | Popular Tags |