##### Coverage Report - com.sun.grizzly.util.OutputWriter

Classes in this File | Line Coverage | Branch Coverage | Complexity
OutputWriter |
35 % | 35/100
23 % | 15/64
| 0.0;0

1 |  |
     /*
2 |  |
      *
3 |  |
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 |  |
      *
5 |  |
      * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
6 |  |
      *
7 |  |
      * The contents of this file are subject to the terms of either the GNU
8 |  |
      * General Public License Version 2 only ("GPL") or the Common Development
9 |  |
      * and Distribution License("CDDL") (collectively, the "License").  You
10 |  |
      * may not use this file except in compliance with the License. You can obtain
11 |  |
      * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
12 |  |
      * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
13 |  |
      * language governing permissions and limitations under the License.
14 |  |
      *
15 |  |
      * When distributing the software, include this License Header Notice in each
16 |  |
      * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
17 |  |
      * Sun designates this particular file as subject to the "Classpath" exception
18 |  |
      * as provided by Sun in the GPL Version 2 section of the License file that
19 |  |
      * accompanied this code.  If applicable, add the following below the License
20 |  |
      * Header, with the fields enclosed by brackets [] replaced by your own
21 |  |
      * identifying information: "Portions Copyrighted [year]
22 |  |
      * [name of copyright owner]"
23 |  |
      *
24 |  |
      * Contributor(s):
25 |  |
      *
26 |  |
      * If you wish your version of this file to be governed by only the CDDL or
27 |  |
      * only the GPL Version 2, indicate your decision by adding "[Contributor]
28 |  |
      * elects to include this software in this distribution under the [CDDL or GPL
29 |  |
      * Version 2] license."  If you don't indicate a single choice of license, a
30 |  |
      * recipient has the option to distribute your version of this file under
31 |  |
      * either the CDDL, the GPL Version 2 or to extend the choice of license to
32 |  |
      * its licensees as provided above.  However, if you add GPL Version 2 code
33 |  |
      * and therefore, elected the GPL Version 2 license, then the option applies
34 |  |
      * only if the new code is made subject to such option by the copyright
35 |  |
      * holder.
36 |  |
      *
37 |  |
      */
38 |  |
39 |  |
     package com.sun.grizzly.util;
40 |  |
41 |  |
     import java.io.IOException;
42 |  |
     import java.net.SocketAddress;
43 |  |
     import java.nio.ByteBuffer;
44 |  |
     import java.nio.channels.DatagramChannel;
45 |  |
     import java.nio.channels.SelectableChannel;
46 |  |
     import java.nio.channels.SelectionKey;
47 |  |
     import java.nio.channels.Selector;
48 |  |
     import java.nio.channels.SocketChannel;
49 |  |
     import java.nio.channels.WritableByteChannel;
50 |  |
51 |  |
     /**
52 |  |
      * NIO utility to flush {@link ByteBuffer}
53 |  |
      *
54 |  |
      * @author Scott Oaks
55 |  |
      */
56 | 0 |
     public class OutputWriter {
57 |  |
58 |  |
         /**
59 |  |
          * The default rime out before closing the connection
60 |  |
          */
61 | 1 |
         private static int defaultWriteTimeout = 30000;
62 |  |
63 |  |
64 |  |
         /**
65 |  |
          * Flush the buffer by looping until the {@link ByteBuffer} is empty
66 |  |
          * @param channel {@link SelectableChannel}
67 |  |
          * @param bb the ByteBuffer to write.
68 |  |
          * @return
69 |  |
          * @throws java.io.IOException
70 |  |
          */
71 |  |
         public static long flushChannel(SelectableChannel channel, ByteBuffer bb)
72 |  |
                 throws IOException{
73 | 4112 |
             return flushChannel(channel,bb,defaultWriteTimeout);
74 |  |
         }
75 |  |
76 |  |
77 |  |
         /**
78 |  |
          * Flush the buffer by looping until the {@link ByteBuffer} is empty
79 |  |
          * @param channel {@link SelectableChannel}
80 |  |
          * @param bb the ByteBuffer to write.
81 |  |
          * @param writeTimeout
82 |  |
          * @return
83 |  |
          * @throws java.io.IOException
84 |  |
          */
85 |  |
         public static long flushChannel(SelectableChannel channel,
86 |  |
                 ByteBuffer bb, long writeTimeout) throws IOException{
87 |  |
88 | 4112 |
             if (bb == null){
89 | 0 |
                 throw new IllegalStateException("Invalid Response State. ByteBuffer"
90 |  |
                         + " cannot be null.");
91 |  |
             }
92 |  |
93 | 4112 |
             if (channel == null){
94 | 0 |
                 throw new IllegalStateException("Invalid Response State. " +
95 |  |
                         "SocketChannel cannot be null.");
96 |  |
             }
97 |  |
98 | 4112 |
             SelectionKey key = null;
99 | 4112 |
             Selector writeSelector = null;
100 | 4112 |
             int attempts = 0;
101 | 4112 |
             int bytesProduced = 0;
102 |  |
             try {
103 | 4112 |
                 WritableByteChannel writableChannel = (WritableByteChannel) channel;
104 | 8224 |
                 while ( bb.hasRemaining() ) {
105 | 4112 |
                     int len = writableChannel.write(bb);
106 | 4112 |
                     if (len > 0){
107 | 4112 |
                         attempts = 0;
108 | 4112 |
                         bytesProduced += len;
109 |  |
                     } else {
110 | 0 |
                         attempts++;
111 | 0 |
                         if ( writeSelector == null ){
112 | 0 |
                             writeSelector = SelectorFactory.getSelector();
113 | 0 |
                             if ( writeSelector == null){
114 |  |
                                 // Continue using the main one.
115 | 0 |
                                 continue;
116 |  |
                             }
117 | 0 |
                             key = channel.register(writeSelector,
118 |  |
                                  SelectionKey.OP_WRITE);
119 |  |
                         }
120 |  |
121 | 0 |
                         if (writeSelector.select(writeTimeout) == 0) {
122 | 0 |
                             if (attempts > 2)
123 | 0 |
                                 throw new IOException("Client disconnected");
124 |  |
                         }
125 |  |
                     }
126 | 4112 |
                 }
127 |  |
             } finally {
128 | 4112 |
                 if (key != null) {
129 | 0 |
                     key.cancel();
130 | 0 |
                     key = null;
131 |  |
                 }
132 |  |
133 | 4112 |
                 if ( writeSelector != null ) {
134 |  |
                     // Cancel the key.
135 | 0 |
                     SelectorFactory.selectNowAndReturnSelector(writeSelector);
136 |  |
                 }
137 |  |
             }
138 | 4112 |
             return bytesProduced;
139 |  |
         }
140 |  |
141 |  |
142 |  |
         /**
143 |  |
          * Flush the buffer by looping until the {@link ByteBuffer} is empty
144 |  |
          * @param socketChannel {@link SocketChannel}
145 |  |
          * @param bb the ByteBuffer to write.
146 |  |
          * @return
147 |  |
          * @throws java.io.IOException
148 |  |
          */
149 |  |
         public static long flushChannel(SocketChannel socketChannel, ByteBuffer[] bb)
150 |  |
                 throws IOException{
151 | 0 |
             return flushChannel(socketChannel,bb,defaultWriteTimeout);
152 |  |
         }
153 |  |
154 |  |
155 |  |
         /**
156 |  |
          * Flush the buffer by looping until the {@link ByteBuffer} is empty
157 |  |
          * @param socketChannel {@link SocketChannel}
158 |  |
          * @param bb the ByteBuffer to write.
159 |  |
          * @param writeTimeout
160 |  |
          * @return
161 |  |
          * @throws java.io.IOException
162 |  |
          */
163 |  |
         public static long flushChannel(SocketChannel socketChannel,
164 |  |
                 ByteBuffer[] bb, long writeTimeout) throws IOException{
165 |  |
166 | 0 |
             if (bb == null){
167 | 0 |
                 throw new IllegalStateException("Invalid Response State. ByteBuffer"
168 |  |
                         + " cannot be null.");
169 |  |
             }
170 |  |
171 | 0 |
             if (socketChannel == null){
172 | 0 |
                 throw new IllegalStateException("Invalid Response State. " +
173 |  |
                         "SocketChannel cannot be null.");
174 |  |
             }
175 |  |
176 | 0 |
             SelectionKey key = null;
177 | 0 |
             Selector writeSelector = null;
178 | 0 |
             int attempts = 0;
179 | 0 |
             long totalBytes = 0;
180 | 0 |
             for (ByteBuffer aBb : bb) {
181 | 0 |
                 totalBytes += aBb.remaining();
182 |  |
             }
183 |  |
184 | 0 |
             long bytesProduced = 0;
185 |  |
             try {
186 | 0 |
                 while (bytesProduced < totalBytes ) {
187 | 0 |
                     long len = socketChannel.write(bb);
188 | 0 |
                     if (len > 0){
189 | 0 |
                         attempts = 0;
190 | 0 |
                         bytesProduced += len;
191 |  |
                     } else {
192 | 0 |
                         if ( writeSelector == null ){
193 | 0 |
                             writeSelector = SelectorFactory.getSelector();
194 | 0 |
                             if ( writeSelector == null){
195 |  |
                                 // Continue using the main one.
196 | 0 |
                                 continue;
197 |  |
                             }
198 |  |
                         }
199 |  |
200 | 0 |
                         key = socketChannel.register(writeSelector,
201 |  |
                                                      SelectionKey.OP_WRITE);
202 |  |
203 | 0 |
                         if (writeSelector.select(writeTimeout) == 0) {
204 | 0 |
                             if (attempts > 2)
205 | 0 |
                                 throw new IOException("Client disconnected");
206 |  |
                         }
207 |  |
                     }
208 | 0 |
                 }
209 |  |
             } finally {
210 | 0 |
                 if (key != null) {
211 | 0 |
                     key.cancel();
212 | 0 |
                     key = null;
213 |  |
                 }
214 |  |
215 | 0 |
                 if ( writeSelector != null ) {
216 |  |
                     // Cancel the key.
217 | 0 |
                     SelectorFactory.selectNowAndReturnSelector(writeSelector);
218 |  |
                 }
219 |  |
             }
220 | 0 |
             return bytesProduced;
221 |  |
         }
222 |  |
223 |  |
224 |  |
         /**
225 |  |
          * Flush the buffer by looping until the {@link ByteBuffer} is empty
226 |  |
          * @param datagramChannel
227 |  |
          * @param socketAddress
228 |  |
          * @param bb the ByteBuffer to write.
229 |  |
          * @return
230 |  |
          * @throws java.io.IOException
231 |  |
          */
232 |  |
         public static long flushChannel(DatagramChannel datagramChannel,
233 |  |
                 SocketAddress socketAddress, ByteBuffer bb)
234 |  |
                     throws IOException{
235 | 1002 |
             return flushChannel(datagramChannel,socketAddress,bb,defaultWriteTimeout);
236 |  |
         }
237 |  |
238 |  |
239 |  |
         /**
240 |  |
          * Flush the buffer by looping until the {@link ByteBuffer} is empty
241 |  |
          * @param datagramChannel
242 |  |
          * @param socketAddress
243 |  |
          * @param bb the ByteBuffer to write.
244 |  |
          * @param writeTimeout
245 |  |
          * @return
246 |  |
          * @throws java.io.IOException
247 |  |
          */
248 |  |
         public static long flushChannel(DatagramChannel datagramChannel,
249 |  |
                 SocketAddress socketAddress, ByteBuffer bb, long writeTimeout)
250 |  |
                     throws IOException{
251 |  |
252 | 1002 |
             if (bb == null){
253 | 0 |
                 throw new IllegalStateException("Invalid Response State. ByteBuffer"
254 |  |
                         + " cannot be null.");
255 |  |
             }
256 |  |
257 | 1002 |
             if (datagramChannel == null){
258 | 0 |
                 throw new IllegalStateException("Invalid Response State. " +
259 |  |
                         "DatagramChannel cannot be null.");
260 |  |
             }
261 |  |
262 | 1002 |
             if (socketAddress == null){
263 | 0 |
                 throw new IllegalStateException("Invalid Response State. " +
264 |  |
                         "SocketAddress cannot be null.");
265 |  |
             }
266 |  |
267 | 1002 |
             SelectionKey key = null;
268 | 1002 |
             Selector writeSelector = null;
269 | 1002 |
             int attempts = 0;
270 | 1002 |
             int bytesProduced = 0;
271 |  |
             try {
272 | 2004 |
                 while ( bb.hasRemaining() ) {
273 | 1002 |
                     int len = datagramChannel.send(bb,socketAddress);
274 | 1002 |
                     if (len > 0){
275 | 1002 |
                         attempts = 0;
276 | 1002 |
                         bytesProduced += len;
277 |  |
                     } else {
278 | 0 |
                         if ( writeSelector == null ){
279 | 0 |
                             writeSelector = SelectorFactory.getSelector();
280 | 0 |
                             if ( writeSelector == null){
281 |  |
                                 // Continue using the main one.
282 | 0 |
                                 continue;
283 |  |
                             }
284 |  |
                         }
285 |  |
286 | 0 |
                         key = datagramChannel.register(writeSelector,
287 |  |
                                                        SelectionKey.OP_WRITE);
288 |  |
289 | 0 |
                         if (writeSelector.select(writeTimeout) == 0) {
290 | 0 |
                             if (attempts > 2)
291 | 0 |
                                 throw new IOException("Client disconnected");
292 |  |
                         } else {
293 | 0 |
                             attempts--;
294 |  |
                         }
295 |  |
                     }
296 | 1002 |
                 }
297 |  |
             } finally {
298 | 1002 |
                 if (key != null) {
299 | 0 |
                     key.cancel();
300 | 0 |
                     key = null;
301 |  |
                 }
302 |  |
303 | 1002 |
                 if ( writeSelector != null ) {
304 |  |
                     // Cancel the key.
305 | 0 |
                     SelectorFactory.selectNowAndReturnSelector(writeSelector);
306 |  |
                 }
307 |  |
             }
308 | 1002 |
             return bytesProduced;
309 |  |
         }
310 |  |
311 |  |
312 |  |
         public static int getDefaultWriteTimeout() {
313 | 0 |
             return defaultWriteTimeout;
314 |  |
         }
315 |  |
316 |  |
317 |  |
         public static void setDefaultWriteTimeout(int aDefaultWriteTimeout) {
318 | 0 |
             defaultWriteTimeout = aDefaultWriteTimeout;
319 | 0 |
         }
320 |  |
     }