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

Classes in this File | Line Coverage | Branch Coverage | Complexity
Utils |
62 % | 55/88
55 % | 26/47
| 11.333333333333334;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 | 1111 |
             int count = 1;
92 | 1111 |
             int byteRead = 0;
93 | 1111 |
             int preReadInputBBPos = byteBuffer.position();
94 | 1111 |
             Selector readSelector = null;
95 | 1111 |
             SelectionKey tmpKey = null;
96 |  |
97 |  |
             try {
98 | 1111 |
                 ReadableByteChannel readableChannel = (ReadableByteChannel) channel;
99 | 2571 |
                 while (count > 0){
100 | 1461 |
                     count = readableChannel.read(byteBuffer);
101 | 1460 |
                     if ( count > -1 )
102 | 1459 |
                         byteRead += count;
103 |  |
                     else
104 | 1 |
                         byteRead = count;
105 |  |
                 }
106 |  |
107 | 1110 |
                 if (byteRead == 0 && byteBuffer.position() == preReadInputBBPos) {
108 | 759 |
                     readSelector = SelectorFactory.getSelector();
109 |  |
110 | 759 |
                     if ( readSelector == null ){
111 | 0 |
                         return 0;
112 |  |
                     }
113 | 759 |
                     count = 1;
114 |  |
115 | 759 |
                     tmpKey = channel.register(readSelector, SelectionKey.OP_READ);
116 | 759 |
                     tmpKey.interestOps(tmpKey.interestOps() | SelectionKey.OP_READ);
117 | 759 |
                     int code = readSelector.select(readTimeout);
118 | 759 |
                     tmpKey.interestOps(
119 |  |
                         tmpKey.interestOps() & (~SelectionKey.OP_READ));
120 |  |
121 | 759 |
                     if ( code == 0 ){
122 | 0 |
                         return 0; // Return on the main Selector and try again.
123 |  |
                     }
124 |  |
125 | 2302 |
                     while (count > 0){
126 | 1543 |
                         count = readableChannel.read(byteBuffer);
127 | 1543 |
                         if ( count > -1 )
128 | 1543 |
                             byteRead += count;
129 |  |
                         else
130 | 0 |
                             byteRead = count;
131 |  |
                     }
132 | 759 |
                 } else if (byteRead == 0 && byteBuffer.position() != preReadInputBBPos) {
133 | 0 |
                     byteRead += (byteBuffer.position() - preReadInputBBPos);
134 |  |
                 }
135 |  |
             } finally {
136 | 1111 |
                 if (tmpKey != null)
137 | 759 |
                     tmpKey.cancel();
138 |  |
139 | 1111 |
                 if ( readSelector != null) {
140 |  |
                     // Bug 6403933
141 | 759 |
                     SelectorFactory.selectNowAndReturnSelector(readSelector);
142 |  |
                 }
143 |  |
             }
144 |  |
145 | 1110 |
             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 |  |
     }