Coverage Report - com.sun.grizzly.util.Utils
 
Classes in this File Line Coverage Branch Coverage Complexity
Utils
64 %
56/88
57 %
27/47
11,333
 
 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.nio.ByteBuffer;
 43  
 import java.nio.channels.ReadableByteChannel;
 44  
 import java.nio.channels.SelectableChannel;
 45  
 import java.nio.channels.SelectionKey;
 46  
 import java.nio.channels.Selector;
 47  
 
 48  
 /**
 49  
  * Class contains set of useful operations commonly used in the framework
 50  
  * 
 51  
  * @author Alexey Stashok
 52  
  * @author Jean-Francois Arcand
 53  
  */
 54  0
 public class Utils {
 55  
      /**
 56  
      * Character translation tables.
 57  
      */
 58  1
     private static final byte[] toLower = new byte[256];
 59  
     
 60  
     /**
 61  
      * Initialize character translation and type tables.
 62  
      */
 63  
     static {
 64  257
         for (int i = 0; i < 256; i++) {
 65  256
             toLower[i] = (byte)i;
 66  
         }
 67  
 
 68  27
         for (int lc = 'a'; lc <= 'z'; lc++) {
 69  26
             int uc = lc + 'A' - 'a';
 70  26
             toLower[uc] = (byte)lc;
 71  
         }
 72  1
     }
 73  
 
 74  
     
 75  
     /**
 76  
      * Method reads data from {@link SelectableChannel} to 
 77  
      * {@link ByteBuffer}. If data is not immediately available - channel
 78  
      *  will be reregistered on temporary {@link Selector} and wait maximum
 79  
      * readTimeout milliseconds for data.
 80  
      * 
 81  
      * @param channel {@link SelectableChannel} to read data from
 82  
      * @param byteBuffer {@link ByteBuffer} to store read data to
 83  
      * @param readTimeout maximum time in millis operation will wait for 
 84  
      * incoming data
 85  
      * 
 86  
      * @return number of bytes were read
 87  
      * @throws <code>IOException</code> if any error was occured during read
 88  
      */
 89  
     public static int readWithTemporarySelector(SelectableChannel channel,
 90  
             ByteBuffer byteBuffer, long readTimeout) throws IOException {
 91  971
         int count = 1;
 92  971
         int byteRead = 0;
 93  971
         int preReadInputBBPos = byteBuffer.position();
 94  971
         Selector readSelector = null;
 95  971
         SelectionKey tmpKey = null;
 96  
 
 97  
         try {
 98  971
             ReadableByteChannel readableChannel = (ReadableByteChannel) channel;
 99  2208
             while (count > 0){
 100  1238
                 count = readableChannel.read(byteBuffer);
 101  1237
                 if ( count > -1 )
 102  1236
                     byteRead += count;
 103  
                 else
 104  1
                     byteRead = count;
 105  
             }            
 106  
             
 107  970
             if (byteRead == 0 && byteBuffer.position() == preReadInputBBPos) {
 108  704
                 readSelector = SelectorFactory.getSelector();
 109  
 
 110  704
                 if ( readSelector == null ){
 111  0
                     return 0;
 112  
                 }
 113  704
                 count = 1;
 114  
                 
 115  704
                 tmpKey = channel.register(readSelector, SelectionKey.OP_READ);
 116  704
                 tmpKey.interestOps(tmpKey.interestOps() | SelectionKey.OP_READ);
 117  704
                 int code = readSelector.select(readTimeout);
 118  704
                 tmpKey.interestOps(
 119  
                     tmpKey.interestOps() & (~SelectionKey.OP_READ));
 120  
 
 121  704
                 if ( code == 0 ){
 122  0
                     return 0; // Return on the main Selector and try again.
 123  
                 }
 124  
 
 125  2147
                 while (count > 0){
 126  1443
                     count = readableChannel.read(byteBuffer);
 127  1443
                     if ( count > -1 )
 128  1442
                         byteRead += count;
 129  
                     else
 130  1
                         byteRead = count;                    
 131  
                 }
 132  704
             } else if (byteRead == 0 && byteBuffer.position() != preReadInputBBPos) {
 133  0
                 byteRead += (byteBuffer.position() - preReadInputBBPos);
 134  
             }
 135  
         } finally {
 136  971
             if (tmpKey != null)
 137  704
                 tmpKey.cancel();
 138  
 
 139  971
             if ( readSelector != null) {
 140  
                 // Bug 6403933
 141  704
                 SelectorFactory.selectNowAndReturnSelector(readSelector);
 142  
             }
 143  
         }
 144  
 
 145  970
         return byteRead;
 146  
     } 
 147  
     
 148  
     
 149  
     /** 
 150  
      * Return the bytes contained between the startByte and the endByte. The ByteBuffer
 151  
      * will be left in the state it was before invoking that method, meaning 
 152  
      * its position and limit will be the same.
 153  
      * 
 154  
      * @param byteBuffer The bytes. 
 155  
      * @param startByte the first byte to look for
 156  
      * @param endByte the second byte to look for
 157  
      * @return The byte[] contained between startByte and endByte
 158  
      */
 159  
     public static byte[] extractBytes(ByteBuffer byteBuffer, 
 160  
             byte startByte, byte endByte) throws IOException{   
 161  
         
 162  0
         int curPosition = byteBuffer.position();
 163  0
         int curLimit = byteBuffer.limit();
 164  
       
 165  0
         if (byteBuffer.position() == 0){
 166  0
             throw new IllegalStateException("Invalid state");
 167  
         }
 168  
        
 169  0
         byteBuffer.position(0);
 170  0
         byteBuffer.limit(curPosition);
 171  0
         int state =0;
 172  0
         int start =0;
 173  0
         int end = 0;  
 174  
         try {                         
 175  
             byte c;            
 176  
             
 177  
             // Rule b - try to determine the context-root
 178  0
             while(byteBuffer.hasRemaining()) {
 179  0
                 c = byteBuffer.get();
 180  0
                 switch(state) {
 181  
                     case 0: // Search for first ' '
 182  0
                         if (c == startByte){
 183  0
                             state = 1;
 184  0
                             start = byteBuffer.position();
 185  
                         }
 186  
                         break;
 187  
                     case 1: 
 188  0
                         if (c == endByte){
 189  0
                             end = byteBuffer.position();
 190  0
                             byte[] bytes = new byte[end - start];
 191  0
                             byteBuffer.position(start);
 192  0
                             byteBuffer.limit(end);
 193  0
                             byteBuffer.get(bytes);
 194  0
                             return bytes;
 195  
                         }
 196  
                         break;
 197  
                     default:
 198  0
                         throw new IllegalArgumentException("Unexpected state");
 199  
                 }      
 200  
             }
 201  0
             throw new IllegalStateException("Unexpected state");
 202  
         } finally {     
 203  0
             byteBuffer.limit(curLimit);
 204  0
             byteBuffer.position(curPosition);                               
 205  
         }       
 206  
     } 
 207  
     
 208  
     
 209  
        
 210  
     /**
 211  
      * Specialized utility method: find a sequence of lower case bytes inside
 212  
      * a ByteBuffer.
 213  
      */
 214  
     public static int findBytes(ByteBuffer byteBuffer, byte[] b) {
 215  9
         int curPosition = byteBuffer.position();
 216  9
         int curLimit = byteBuffer.limit();
 217  
       
 218  9
         if (byteBuffer.position() == 0){
 219  0
             throw new IllegalStateException("Invalid state");
 220  
         }
 221  
        
 222  9
         byteBuffer.position(0);
 223  9
         byteBuffer.limit(curPosition);
 224  
         try {                         
 225  9
             byte first = b[0];
 226  9
             int start = 0;
 227  9
             int end = curPosition;
 228  
 
 229  
             // Look for first char 
 230  9
             int srcEnd = b.length;
 231  
 
 232  99
             for (int i = start; i <= (end - srcEnd); i++) {
 233  99
                 if ((toLower[byteBuffer.get(i) & 0xff] & 0xff) != first) continue;
 234  
                 // found first char, now look for a match
 235  27
                 int myPos = i+1;
 236  27
                 for (int srcPos = 1; srcPos < srcEnd; ) {
 237  108
                         if ((toLower[byteBuffer.get(myPos++) & 0xff] & 0xff) != b[srcPos++])
 238  18
                     break;
 239  90
                         if (srcPos == srcEnd) return i - start; // found it
 240  
                 }
 241  
             }
 242  0
             return -1;
 243  
         } finally {
 244  9
             byteBuffer.limit(curLimit);
 245  9
             byteBuffer.position(curPosition);                
 246  
         }
 247  
     }
 248  
 }