KickJava   Java API By Example, From Geeks To Geeks.

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


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.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 /**
26  * This is an OutputStream constructed from list of ByteBuffers. This is
27  * used in non-blocking mode.
28  * @since 1.4.5
29  * @author Akshathkumar Shetty
30  */

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     /**
38      * Sets the debug flag. When debug is set to <code>true</code>
39      * one can see number of bytes written.
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     private ArrayList bufferList;
56     private ByteBuffer lastByteBuffer = null;
57     private NonBlockingClientHandler handler;
58     private Object JavaDoc toNotify = null;
59
60     /**
61      * Creates a new ByteBufferOutputStream using the given list as its base
62      * and ClientHandler as the target channel.
63      */

64     public ByteBufferOutputStream(ArrayList bufferList, ClientHandler handler) {
65         if(bufferList==null || handler==null)
66             throw new IllegalArgumentException JavaDoc("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 JavaDoc 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 JavaDoc 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     //returns flag indicating if full write was done
160
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 JavaDoc 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 JavaDoc 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 JavaDoc toNotify) {
231         if(lastByteBuffer!=null) {
232             if(this.toNotify!=null) {
233                 throw new IllegalStateException JavaDoc("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 JavaDoc("toNotify object was already set!");
243             }
244             this.toNotify = toNotify;
245             return true;
246         }
247     }
248 }
249
Popular Tags