001: //========================================================================
002: // Parts Copyright 2006 Mort Bay Consulting Pty. Ltd.
003: //------------------------------------------------------------------------
004: // Licensed under the Apache License, Version 2.0 (the "License");
005: // you may not use this file except in compliance with the License.
006: // You may obtain a copy of the License at
007: // http://www.apache.org/licenses/LICENSE-2.0
008: // Unless required by applicable law or agreed to in writing, software
009: // distributed under the License is distributed on an "AS IS" BASIS,
010: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: // See the License for the specific language governing permissions and
012: // limitations under the License.
013: //========================================================================
014:
015: package org.mortbay.jetty.grizzly;
016:
017: import com.sun.enterprise.web.portunif.ProtocolFinder;
018: import com.sun.enterprise.web.portunif.util.ProtocolInfo;
019: import java.io.IOException;
020: import java.nio.BufferUnderflowException;
021: import java.nio.ByteBuffer;
022: import java.nio.channels.SelectionKey;
023: import java.nio.channels.SocketChannel;
024: import javax.net.ssl.SSLEngine;
025:
026: /**
027: * A <code>ProtocolFinder</code> implementation that parse the available
028: * SocketChannel bytes looking for the 'http' bytes. An http request will
029: * always has the form of:
030: *
031: * METHOD URI PROTOCOL/VERSION
032: *
033: * example: GET / HTTP/1.1
034: *
035: * The algorithm will try to find the protocol token. Once found, the request
036: * will be redirected from Grizzly embedded in GlassFish to Jetty.
037: *
038: * @author Jeanfrancois Arcand
039: */
040: public class JettyProtocolFinder implements ProtocolFinder {
041:
042: public JettyProtocolFinder() {
043: }
044:
045: /**
046: * Try to find if the current connection is using the HTTP protocol.
047: *
048: * @param ProtocolInfo The ProtocolInfo that contains the information
049: * about the current protocol.
050: */
051: public void find(ProtocolInfo protocolInfo) {
052: SelectionKey key = protocolInfo.key;
053: SocketChannel socketChannel = (SocketChannel) key.channel();
054: ByteBuffer byteBuffer = protocolInfo.byteBuffer;
055:
056: int loop = 0;
057: int bufferSize = 0;
058: int count = -1;
059:
060: if (protocolInfo.bytesRead == 0) {
061: try {
062: while (socketChannel.isOpen()
063: && ((count = socketChannel.read(byteBuffer)) > -1)) {
064:
065: if (count == 0) {
066: loop++;
067: if (loop > 2) {
068: break;
069: }
070: continue;
071: }
072: }
073: } catch (IOException ex) {
074: ;
075: } finally {
076: if (count == -1) {
077: return;
078: }
079: protocolInfo.bytesRead = count;
080: }
081: }
082: boolean isFound = false;
083:
084: int curPosition = byteBuffer.position();
085: int curLimit = byteBuffer.limit();
086:
087: // Rule a - If nothing, return to the Selector.
088: if (byteBuffer.position() == 0) {
089: protocolInfo.byteBuffer = byteBuffer;
090: return;
091: }
092:
093: byteBuffer.position(0);
094: byteBuffer.limit(curPosition);
095: int state = 0;
096: int start = 0;
097: int end = 0;
098:
099: try {
100: byte c;
101:
102: // Rule b - try to determine the context-root
103: while (byteBuffer.hasRemaining()) {
104: c = byteBuffer.get();
105: // State Machine
106: // 0 - Search for the first SPACE ' ' between the method and the
107: // the request URI
108: // 1 - Search for the second SPACE ' ' between the request URI
109: // and the method
110: switch (state) {
111: case 0: // Search for first ' '
112: if (c == 0x20) {
113: state = 1;
114: start = byteBuffer.position();
115: }
116: break;
117: case 1: // Search for next ' '
118: if (c == 0x20) {
119: state = 2;
120: end = byteBuffer.position() - 1;
121: byteBuffer.position(start);
122: byte[] requestURI = new byte[end - start];
123: byteBuffer.get(requestURI);
124: protocolInfo.requestURI = new String(requestURI);
125: }
126: break;
127: case 2: // Search for /
128: if (c == 0x2f) {
129: protocolInfo.protocol = protocolInfo.isSecure ? "https"
130: : "jetty-http";
131: protocolInfo.byteBuffer = byteBuffer;
132: protocolInfo.socketChannel = (SocketChannel) key
133: .channel();
134: return;
135: }
136: break;
137: default:
138: throw new IllegalArgumentException(
139: "Unexpected state");
140: }
141: }
142: } catch (BufferUnderflowException bue) {
143: } finally {
144: byteBuffer.limit(curLimit);
145: byteBuffer.position(curPosition);
146: protocolInfo.bytesRead = byteBuffer.position();
147: }
148: return;
149: }
150:
151: }
|