Coverage Report - com.sun.grizzly.util.OutputWriter
 
Classes in this File Line Coverage Branch Coverage Complexity
OutputWriter
35 %
35/100
23 %
15/64
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  4093
         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  4093
         if (bb == null){
 89  0
             throw new IllegalStateException("Invalid Response State. ByteBuffer" 
 90  
                     + " cannot be null.");
 91  
         }
 92  
         
 93  4093
         if (channel == null){
 94  0
             throw new IllegalStateException("Invalid Response State. " +
 95  
                     "SocketChannel cannot be null.");
 96  
         }       
 97  
         
 98  4093
         SelectionKey key = null;
 99  4093
         Selector writeSelector = null;
 100  4093
         int attempts = 0;
 101  4093
         int bytesProduced = 0;
 102  
         try {
 103  4093
             WritableByteChannel writableChannel = (WritableByteChannel) channel;
 104  8185
             while ( bb.hasRemaining() ) {
 105  4093
                 int len = writableChannel.write(bb);
 106  4092
                 if (len > 0){
 107  4092
                     attempts = 0;
 108  4092
                     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  4092
             }   
 127  
         } finally {
 128  4093
             if (key != null) {
 129  0
                 key.cancel();
 130  0
                 key = null;
 131  
             }
 132  
             
 133  4093
             if ( writeSelector != null ) {
 134  
                 // Cancel the key.
 135  0
                 SelectorFactory.selectNowAndReturnSelector(writeSelector);
 136  
             }
 137  
         }
 138  4092
         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  
 }