KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > web > connector > grizzly > algorithms > StateMachineAlgorithm


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.web.connector.grizzly.algorithms;
24
25 import com.sun.enterprise.web.connector.grizzly.Handler;
26 import com.sun.enterprise.web.connector.grizzly.SelectorThread;
27 import com.sun.enterprise.web.connector.grizzly.handlers.NoParsingHandler;
28
29 import java.nio.ByteBuffer JavaDoc;
30 import java.nio.BufferUnderflowException JavaDoc;
31 import java.util.logging.Level JavaDoc;
32
33 /**
34  * Predict if the NIO channel has been fully read or not. This lagorithm will
35  * first search for the content-length header, and use that value to determine if
36  * the bytes has been fully read or not. If the content-length isn't included,
37  * it will search for the end of the HTTP stream, which is a '\r\n'
38  *
39  * @author Scott Oaks.
40  * @author Jean-Francois Arcand
41  */

42 public final class StateMachineAlgorithm extends StreamAlgorithmBase{
43
44
45     // ---------------------------------------------- Constructor ----------/
46

47     
48     public StateMachineAlgorithm() {
49         handler = new NoParsingHandler(getPort());
50     }
51     
52
53     /**
54      * Parse the <code>ByteBuffer</code> and try to determine if the bytes
55      * stream has been fully read from the <code>SocketChannel</code>.
56      *
57      * Drain the <code>SocketChannel</code> and determine if the request bytes
58      * has been fully read. For POST method, parse the bytes and seek for the
59      * content-type header to determine the length of the request bytes.
60      * @return true if we need to call back the <code>SelectorThread</code>
61      * This occurs when the stream doesn't contains all the
62      * request bytes.
63      * false if the stream contains all request bytes.
64      *
65      * @paran byteBuffer the bytes read.
66      * @return true if the algorithm determines the end of the stream.
67      */

68     public boolean parse(ByteBuffer JavaDoc byteBuffer){
69         boolean isFound = false;
70                           
71         curLimit = byteBuffer.limit();
72         curPosition = byteBuffer.position();
73         
74         // Rule a - if we know the content length, verify all bytes are read
75
if ( contentLength != -1 ){
76             isFound = ((contentLength + headerLength) <= byteBuffer.position());
77             
78             if (isFound)
79                 byteBuffer.flip();
80             
81             return isFound;
82         }
83
84         // Rule b - If nothing, return to the Selector.
85
if (byteBuffer.position() == 0)
86             return false;
87
88         if (SelectorThread.logger().isLoggable(Level.FINEST))
89             SelectorThread.logger().log(Level.FINEST,dump(byteBuffer));
90         
91         byteBuffer.flip();
92         try {
93             byte c;
94             byte prev_c = ' ';
95             
96             try{
97                 if ( state != 0 ){
98                     byteBuffer.position(lastStatePosition);
99                 }
100             } catch (RuntimeException JavaDoc ex){
101                 // If for any reason we aren't able to recover, use the bytes as
102
// it is (so DoS are avoided).
103
state = 0;
104                 lastStatePosition = -1;
105             }
106             
107             // Rule c - try to determine the content-length
108
while(byteBuffer.hasRemaining()) {
109                 c = byteBuffer.get();
110
111                 // State Machine
112
// 0: no special characters have been read, but at beginning
113
// of line
114
// 1: not at beginning of line; parse until the next line
115
// 2: read initial G
116
// 3: read initial GE
117
// 4: read initial GET -- now we know we have a GET request;
118
// we can parse until we see \r\n\r\n
119
// we stay state 4-7 until we're done
120
// 8: read initial P
121
// 9: read initial PO
122
// 10: read initial POS
123
// 11: read initial POST -- now we can look for content-length
124
// we can parse until we see content-lenth
125
// we stay in state 12-27 until we've got length
126
// 28: read all of post; parse until \r\n\r\n (see state 4)
127

128                 // ************************************************************
129
// XXX This algorithm needs to use
130
// InternalInputBuffer.parseRequestLine instead
131
// ************************************************************
132
switch(state) {
133                     case 0: // looking for g or p
134
if (c == 0x47 || c == 0x67)
135                             state = 2;
136                         else if (c == 0x50 || c == 0x70)
137                             state = 8;
138                         else if (c != 0x0d && c != 0x0a)
139                             state = 1;
140                         break;
141                     case 1: // looking for next line
142
if (c == 0x0a || c == 0x0d)
143                             state = 0;
144                         break;
145                     case 2: // looking for e
146
if (c == 0x45 || c == 0x65)
147                             state = 3;
148                         else state = 1;
149                         break;
150                     case 3: // looking for t
151
if (c == 0x54 || c == 0x74)
152                             state = 4;
153                         else state = 1;
154                         break;
155                     case 4: // \r
156
if ( c == 0x0a ){
157                             state = 5;
158                         }
159                         break;
160                     case 5: // \n or \r
161
if ( c == 0x0d || c == 0x0a){
162                             headerLength = byteBuffer.position();
163                             isFound = true;
164                             return isFound;
165                         }
166                         else state = 4;
167                         break;
168                     case 8: // looking for o
169
if (c == 0x4F || c == 0x6F)
170                             state = 9;
171                         else state = 1;
172                         break;
173                     case 9: // looking for s
174
if (c == 0x73 || c == 0x53)
175                             state = 10;
176                         else state = 1;
177                         break;
178                     case 10: // looking for t
179
if (c == 0x74 || c == 0x54)
180                             state = 11;
181                         else state = 1;
182                         break;
183                     case 11: // looking for new line
184
if (c == 0x0a || c == 0x0d)
185                             state = 12;
186                         else state = 11;
187                         break;
188                     case 12: // looking for c
189
if (c == 0x43 || c == 0x63)
190                             state = 13;
191                         else if (prev_c == 0x0a
192                             && byteBuffer.position() == curPosition) {
193                             headerLength = byteBuffer.position();
194                             // Content-length not specified.
195
isFound = true;
196                             return isFound;
197                         } else state = 12;
198                         break;
199                     case 13: // looking for o
200
if (c == 0x4F || c == 0x6F)
201                             state = 14;
202                         else state = 11;
203                         break;
204                     case 14: // looking for n
205
if (c == 0x4E || c == 0x6E)
206                             state = 15;
207                         else state = 11;
208                         break;
209                     case 15: // looking for t
210
if (c == 0x54 || c == 0x74)
211                             state = 16;
212                         else state = 11;
213                         break;
214                     case 16: // looking for e
215
if (c == 0x45 || c == 0x65)
216                             state = 17;
217                         else state = 11;
218                         break;
219                     case 17: // looking for n
220
if (c == 0x4E || c == 0x6E)
221                             state = 18;
222                         else state = 11;
223                         break;
224                     case 18: // looking for t
225
if (c == 0x54 || c == 0x74)
226                             state = 19;
227                         else state = 11;
228                         break;
229                     case 19: // -
230
if (c == 0x2D || c == 0x2D)
231                             state = 20;
232                         else state = 11;
233                         break;
234                     case 20: // l
235
if (c == 0x4C || c == 0x6C)
236                             state = 21;
237                         else state = 11;
238                         break;
239                     case 21: // e
240
if (c == 0x45 || c == 0x65)
241                             state = 22;
242                         else state = 11;
243                         break;
244                     case 22: // n
245
if (c == 0x4E || c == 0x6E)
246                             state = 23;
247                         else state = 11;
248                         break;
249                     case 23: // g
250
if (c == 0x47 || c == 0x67)
251                             state = 24;
252                         else state = 11;
253                         break;
254                     case 24: // t
255
if (c == 0x54 || c == 0x74)
256                             state = 25;
257                         else state = 11;
258                         break;
259                     case 25: // h
260
if (c == 0x48 || c == 0x68)
261                             state = 26;
262                         else state = 11;
263                         break;
264                     case 26: // :
265
if (c == 0x3a)
266                             state = 27;
267                         else state = 11;
268                         break;
269                     case 27: // read length until \r
270
while (c < 0x30 || c > 0x39) {
271                             // Read past the whitespace between the :
272
// and the length
273
c = byteBuffer.get();
274                         }
275                         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
276                         while (c >= 0x30 && c <= 0x39) {
277                             sb.append((char) c);
278                             c = byteBuffer.get();
279                         }
280                         contentLength = Integer.parseInt(sb.toString());
281                         // XXX: We've already read the character past the length.
282
// Can it ever not be 0x0d? Would that be an error
283
// otherwise?
284
if (c == 0x0d)
285                             state = 29;
286                         else state = 28;
287                         break;
288                     case 28: // looking for \r
289
if (c == 0x0d)
290                             state = 29;
291                         break;
292                     case 29: // looking for \n
293
if (c == 0x0a)
294                             state = 30;
295                         else state = 28;
296                         break;
297                     case 30: // looking for \r
298
if (c == 0x0d)
299                             state = 31;
300                         else state = 28;
301                         break;
302                     case 31: // looking for \n
303
if (c == 0x0a){
304                             headerLength = byteBuffer.position();
305                             // wait until we have fully read the request body.
306
isFound = ((contentLength + headerLength)
307                                                          <= byteBuffer.limit());
308                             return isFound;
309                         }
310                         else state = 28;
311                         break;
312                     default:
313                         throw new IllegalArgumentException JavaDoc("Unexpected state");
314                     }
315                     prev_c = c;
316                 }
317                 
318                 // NEITHER A GET OR A POST
319
if ( state == 0 ) {
320                     isFound = true;
321                 }
322             
323                 return isFound;
324         } catch (BufferUnderflowException JavaDoc bue) {
325             SelectorThread.logger().log(Level.SEVERE,"readTask.bufferunderflow", bue);
326             return false;
327         } finally {
328             if ( headerLength == -1 && (state > 0)){
329                 // This means we weren't able to able to find the content-length
330
// or the end of the stream.
331
lastStatePosition = byteBuffer.limit();
332             }
333             byteBuffer.limit(curLimit);
334             byteBuffer.position(curPosition);
335             
336             if (isFound){
337                 byteBuffer.flip();
338             }
339         }
340     }
341
342     
343     /**
344      * Return the <code>Handler</code> used by this algorithm.
345      */

346     public Handler getHandler(){
347        ((NoParsingHandler)handler).attachChannel(socketChannel);
348        return handler;
349     }
350      
351     
352     /***
353      * Recycle this object.
354      */

355     public void recycle(){
356         super.recycle();
357         
358         socketChannel = null;
359         if ( handler != null){
360             ((NoParsingHandler)handler).attachChannel(null);
361         }
362     }
363 }
364
Popular Tags