Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    *
    * Copyright (c) 1997-2014 Oracle and/or its affiliates. All rights reserved.
    *
    * The contents of this file are subject to the terms of either the GNU
    * General Public License Version 2 only ("GPL") or the Common Development
    * and Distribution License("CDDL") (collectively, the "License").  You
    * may not use this file except in compliance with the License.  You can
   * obtain a copy of the License at
   * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
   * or packager/legal/LICENSE.txt.  See the License for the specific
   * language governing permissions and limitations under the License.
   *
   * When distributing the software, include this License Header Notice in each
   * file and include the License file at packager/legal/LICENSE.txt.
   *
   * GPL Classpath Exception:
   * Oracle designates this particular file as subject to the "Classpath"
   * exception as provided by Oracle in the GPL Version 2 section of the License
   * file that accompanied this code.
   *
   * Modifications:
   * If applicable, add the following below the License Header, with the fields
   * enclosed by brackets [] replaced by your own identifying information:
   * "Portions Copyright [year] [name of copyright owner]"
   *
   * Contributor(s):
   * If you wish your version of this file to be governed by only the CDDL or
   * only the GPL Version 2, indicate your decision by adding "[Contributor]
   * elects to include this software in this distribution under the [CDDL or GPL
   * Version 2] license."  If you don't indicate a single choice of license, a
   * recipient has the option to distribute your version of this file under
   * either the CDDL, the GPL Version 2 or to extend the choice of license to
   * its licensees as provided above.  However, if you add GPL Version 2 code
   * and therefore, elected the GPL Version 2 license, then the option applies
   * only if the new code is made subject to such option by the copyright
   * holder.
   */
  
  /*
   *  Copyright 1999-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package com.sun.enterprise.web.connector.grizzly;
  
  
  import java.net.Socket;
  
  
  
Process HTTP request. This class is based on org.apache.coyote.http11.Http11Processor

Author(s):
Jean-Francois Arcand
 
 public class DefaultProcessorTask extends TaskBase implements Processor
         ActionHookProcessorTask {
     private static final Logger LOGGER =
             Logger.getLogger(DefaultProcessorTask.class.getName());
     private static final Level LOG_LEVEL = .;

    
Associated adapter.
 
     protected Adapter adapter = null;


    
Request object.
 
     protected Request request = null;


    
Response object.
 
     protected Response response = null;


    
Input.
 
     public InternalInputBuffer inputBuffer = null;


    
Output.
 
     protected InternalOutputBuffer outputBuffer = null;


    
State flag.
 
     protected boolean started = false;


    
Error flag.
 
     protected boolean error = false;


    
Keep-alive.
 
     protected boolean keepAlive = true;
    
    
    
Connection: value
 
     protected boolean connectionHeaderValueSet = false;

    
    
HTTP/1.1 flag.
 
     protected boolean http11 = true;


    
HTTP/0.9 flag.
 
     protected boolean http09 = false;


    
Content delimitator for the request (if false, the connection will be closed at the end of the request).
 
     protected boolean contentDelimitation = true;


    
SSL information.
 
     protected SSLSupport sslSupport;


    
Socket associated with the current connection.
 
     protected Socket socket;


    
Remote Address associated with the current connection.
 
     protected String remoteAddr = null;


    
Remote Host associated with the current connection.
 
     protected String remoteHost = null;
    
    
    
Local Host associated with the current connection.
 
     protected String localName = null;
        
    
    
Local port to which the socket is connected
 
     protected int localPort = -1;
    
    
    
Remote port to which the socket is connected
 
     protected int remotePort = -1;
    
    
    
The local Host address.
 
     protected String localAddr = null


    
Maximum timeout on uploads. 5 minutes as in Apache HTTPD server.
 
     protected int uploadTimeout = .;


    
Max post size.
 
     protected int maxPostSize = 2 * 1024 * 1024;


    
Host name (used to avoid useless B2C conversion on the host name).
 
     protected char[] hostNameC = new char[0];


    
The taskContext associated with this object. The taskContext contains information about the current connection.
 
     protected TaskContext taskContext;    
    
    
    
The TaskEvent associated with this task.
 
     protected TaskEvent<TaskContexttaskEvent;
    
    
    
Has the request associated with this ProcessorTask been registered with the RequestGroupInfo
 
     protected boolean hasRequestInfoRegistered = false;
    
    
    
Default HTTP header buffer size.
 
     protected int maxHttpHeaderSize = .;

    
    
The number of requests ProcessorTask has proceeded.
 
     protected static int requestCount;

    
    
The input request buffer size.
 
     protected int requestBufferSize = .;


    
ObjectName under which this ProcessorTask will be JMX-registered if monitoring has been turned on
 
     protected ObjectName oname;
    
    
    
Allow client of this class to force connection closing.
 
     protected boolean dropConnection = false;
    
    
    
The current keep-alive count left before closing the connection.
 
     protected int keepAliveLeft;
  
     
    
The handler used by this Task to manipulate the request.
 
     protected Handler handler;
    
    
    
The default response-type
 
     protected String defaultResponseType = .;
     
    
    
The forced request-type
 
     protected String forcedRequestType = .;     
    
    
    
Is asynchronous mode enabled?
 
     protected boolean asyncExecution = false;
    
    
    
The code>RequestInfo used to gather stats.
 
     protected RequestInfo requestInfo;
    
    
    
When the asynchronous mode is enabled, the execution of this object will be delegated to the AsyncHandler
 
     protected AsyncHandler asyncHandler;

    
    
Max keep-alive request before timing out.
 
     protected int maxKeepAliveRequests = .;  
     
 // ----------------------------------------------- Compression Support ---//
 

    
List of user agents to not use gzip with
 
     protected String[] noCompressionUserAgents = null;


    
List of MIMES which could be gzipped
 
     protected String[] compressableMimeTypes 
             = { "text/html""text/xml""text/plain" };
    
   
    
Allowed compression level.
 
     protected int compressionLevel = 0;


    
Minimum contentsize to make compression.
 
     protected int compressionMinSize = 2048;
    
    
    
List of restricted user agents.
 
     protected String[] restrictedUserAgents = null;

        
    
Buffer the response until the buffer is full.
 
     protected boolean bufferResponse = true;
    
    
    
Flag to disable setting a different time-out on uploads.
 
     protected boolean disableUploadTimeout = true;  
     
     private final static String USE_KEEP_ALIVE =
                 "com.sun.grizzly.useKeepAliveAlgorithm";   
     
     private boolean useKeepAliveAlgorithm = false;
 
     // Has processing of this object completed.
     private boolean isProcessingCompleted = false;
     
     // ----------------------------------------------------- Constructor ---- //
 
     public DefaultProcessorTask(){
         this(true);
     }
        
     
     public DefaultProcessorTask(boolean init){    
          = ;
         if (init) {
             initialize();
         }
     }
     
     
     public DefaultProcessorTask(boolean initboolean bufferResponse){    
         this. = bufferResponse;
 
          = ;
         if (init) {
             initialize();
         }
     }
    
    
    
Initialize the stream and the buffer used to parse the request.
 
     public void initialize(){
          = true;   
          = new Request();
 
          = new Response();
         .setHook(this);
         
         if (){
              = new AsynchronousOutputBuffer(
                                                      ,
                                                      );        
         } else {
              = new SocketChannelOutputBuffer(
                                                      ,
                                                      );           
         }
        
         .setResponse();
 
         initializeFilters();
         
         if (System.getProperty() != null) {
              =
                         Boolean.valueOf(
                             System.getProperty()).booleanValue();
         }
     }
 
 
     // ----------------------------------------------------- Thread run ---- //
     
    
     
Execute the HTTP request by parsing the header/body, and then by delegating the process to the Catalina container.
 
     public void doTask() throws IOException{
         try {
             process(.getInputStream(),
                     .getOutputStream());
         } catch(IOException ex){
             SelectorThread.logger().log(.,
                     "processorTask.errorProcessingRequest"ex);
         } catch(Throwable ex){
             SelectorThread.logger().log(.,
                     "processorTask.errorProcessingRequest"ex);
         } finally {
             terminateProcess();        
         }
     }
 
  
      // --------------------------------------------------------- TaskEvent ---// 
         
      
     @Override
     public void taskEvent(TaskEvent event) {
         if (.isLoggable()) {
             .log("DefaultProcessorTask.taskEvent dpt={0} event.status={1}",
                     new Object[]{thisevent.getStatus()});
         }
         if ( event.getStatus() == .) {
              = (TaskContext)event.attachement();
             if ( == null) {
                  = new TaskEvent<TaskContext>();
             }
             
             .attach();
 
             if ( ! ) {
                 execute();
             } else {
                 .handle(this);
             }
         }
     }
 
     // -------------------------------------------------------------------- //
 
    
    
Pre process the request by decoding the request line and the header.
  
     public void preProcess() throws Exception {
                    .getOutputStream());
     }
    
    
    
Pre process the request by decoding the request line and the header.

Parameters:
input the InputStream to read bytes
output the OutputStream to write bytes
      
     public void preProcess(InputStream inputOutputStream output)
                                                             throws Exception {
         
         // Make sure this object has been initialized.
         if ( ! ){
             initialize();
         }
         // Setting up the I/O
         .setInputStream(input);
         if (  != null ) {
             SocketChannelOutputBuffer channelOutputBuffer = 
                     ((SocketChannelOutputBuffer));
             channelOutputBuffer.setChannel((SocketChannel).channel());
         } 
         configPreProcess();
     }
        
    
    
Prepare this object before parsing the request.
 
     protected void configPreProcess() throws Exception {
         if (isMonitoringEnabled()){
             .
                 fireAdapterEvent(.,
                     .getRequestProcessor());
         }
                     
         if.getDomain() != null 
                 && isMonitoringEnabled() 
                 && ! ) {
             registerMonitoring();
         } else if (!isMonitoringEnabled() && ) {
             unregisterMonitoring();
         } 
         
         if (isMonitoringEnabled()) {
              = .getRequestProcessor();
             .setWorkerThreadID(Thread.currentThread().getId());
         }
         
         // Set the remote address
          = null;
          = null;
          = null;
          = null;
          = -1;
          = -1;
          = false;
         
         // Error flag
          = false;
          = true;
 
         if (.getServerPort() == 0) {
             .setServerPort(.getPort());
         }        
     }

    
    
Process an HTTP request using a non blocking socket
       
     protected boolean doProcess() throws Exception {
         return doProcess(.getInputStream(),
                          .getOutputStream());
     }
    
    
    
Process an HTTP request using a non blocking socket

Parameters:
input the InputStream to read bytes
output the OutputStream to write bytes
          
     protected boolean doProcess(InputStream inputOutputStream output)
                                                             throws Exception{        
         do {
             prepareForNextRequest();
             
             boolean exitWhile = parseRequest(inputoutputfalse);
             if (exitWhile) {
                 return exitWhile;
             }
             invokeAdapter();
             postResponse();  
         } while (hasNextRequest());
         return ;
     }
 
     public boolean hasNextRequest() {
         return  && ! && .available() > 0;
     }
     
     public void prepareForNextRequest() {
          = false;
     }
    
    
Prepare and post the response.

Parameters:
input the InputStream to read bytes
output the OutputStream to write bytes
        
     public void postResponse() throws Exception {
         if (.isLoggable()) {
             .log("DefaultProcessorTask.postResponse dpt={0} isProcessingCompleted={1}",
                     new Object[]{this});
         }
         if () {
             return;
         }
         
         finishResponse();
     }
     
     public void finishResponse() {
          = true;
         
         try {
             .afterService(,);
         } catch (Exception ex) {
              = true;
             SelectorThread.logger().log(.,
                     "processorTask.errorFinishingRequest"ex);            
         }
         
         // Finish the handling of the request
         try {
              .endRequest();
         } catch (IOException e) {
              = true;
         } catch (Throwable t) {
             SelectorThread.logger().log(.,
                     "processorTask.errorFinishingRequest"t);
             // 500 - Internal Server Error
             .setStatus(500);
              = true;
         }
         try {
             .endRequest();
         } catch (IOException e) {
              = true;
         } catch (Throwable t) {
             SelectorThread.logger().log(.,
                     "processorTask.errorFinishingResponse"t);
              = true;
         }
 
         // If there was an error, make sure the request is counted as
         // and error, and update the statistics counter
         if () {
             .setStatus(500);
         }
 
         if (isMonitoringEnabled()) {
             .updateCounters();
                     .getRequestProcessor());              
         }
 
         // Next request
         .nextRequest();
         .nextRequest();
     }
    
    
    
Invoke the Adapter, which usualy invoke the Servlet Container.
 
     public void invokeAdapter(){
         // Process the request in the adapter
         if (.isLoggable()) {
             .log("DefaultProcessorTask.invokeAdapter adapter={0}, error={1}",
                     new Object[]{});
         }
         
         if (!) {
             try {
                 .service();
                 // Handle when the response was committed before a serious
                 // error occurred.  Throwing a ServletException should both
                 // set the status to 500 and set the errorException.
                 // If we fail here, then the response is likely already 
                 // committed, so we can't try and set headers.
                 if( && !) { // Avoid checking twice.
                      = .getErrorException() != null ||
                             statusDropsConnection(.getStatus());
                 }
             } catch (InterruptedIOException e) {
                  = true;
             } catch (Throwable t) {
                 SelectorThread.logger().log(.,
                         "processorTask.serviceError"t);
                 // 500 - Internal Server Error
                 .setStatus(500);
                  = true;
             }
             
             if (.isLoggable()) {
                 .log("DefaultProcessorTask.invokeAdapter_1 status={0}, error={1}, isKeepAlive={2}",
                         new Object[]{.getStatus(), isKeepAlive()});
             }
         }
     }
    
    
    
Parse the request line and the http header.
 
     public boolean parseRequest() throws Exception {
         return parseRequest(.getInputStream(),
                      .getOutputStream(), true);
     }    
    
    
    
Parse the request line and the http header.

Parameters:
input the InputStream to read bytes
output the OutputStream to write bytes
     
     public boolean parseRequest(InputStream inputOutputStream output,
             boolean keptAlivethrows Exception {
         
         // Parsing the request header
         try {
             if (isMonitoringEnabled()){
                 .fireAdapterEvent(.
                         .getRequestProcessor());
             }
 
             int soTimeout = getSoTimeout(input);
 
             if () {
                 float threadRatio =
                         (floatgetPipeline().getCurrentThreadsBusy() / (floatgetPipeline().getMaxThreads();
 
                 if ((threadRatio > 0.33) && (threadRatio <= 0.66)) {
                     soTimeout = soTimeout / 2;
                 } else if (threadRatio > 0.66) {
                     soTimeout = soTimeout / 5;
                      = 1;
                 }
                 setSoTimeout(inputsoTimeout);
             }
 
             configureTransactionTimeout();
             
             .parseRequestLine();
             if (isMonitoringEnabled()) {
                 .getRequestProcessor().setRequestCompletionTime(0);
             }
 
             .setStartTime(System.currentTimeMillis());
             if (  != null && 
                     .handle(,.)
                         == .){
                 keepAlive(.getMimeHeaders());
                 return true;
             }
 
             if (! && (getSelectionKey() != null) || isBlockingStream(input)) {
                 setSoTimeout(input);
             }
             
             if ( > 0 && -- == 0) {
                  = false;      
             }
             
             keptAlive = true;
             .parseHeaders();
         
             if (  != null && 
                     .handle(,.)
                         == .){
                  = (.protocol().equals(.));
                 return true;
             }
 
             if ( .isEnableNioLogging() ){                               
                 SelectorThread.logger().log(.
                         "SocketChannel request line" + .channel() + " is: " 
                         + );
                 
                 SelectorThread.logger().log(."SocketChannel headers" 
                         + .channel() + " are: "
                         + .getMimeHeaders());
             }                       
         } catch (IOException e) {
             SelectorThread.logger().log(.,
                     "processorTask.nonBlockingError"e);
              = true;
              = false;
             return true;
         } catch (Throwable t) {
             SelectorThread.logger().log(.,
                     "processorTask.nonBlockingError"t);
             // 400 - Bad Request
             .setStatus(400);
              = true;
         }
 
         // Setting up filters, and parse some request headers
         try {
             prepareRequest();
         } catch (Throwable t) {
             SelectorThread.logger().log(.,
                     "processorTask.createRequestError"t);
             // 400 - Internal Server Error
             .setStatus(400);
              = true;
         }
         return false;
     }
    
    
    
Post process the http request, after the response has been commited.
       
     public void postProcess() throws Exception {
                     .getOutputStream());
     }      
    
    
    
Post process the http request, after the response has been commited.
       
     public void postProcess(InputStream inputOutputStream output)
                                                             throws Exception {
         if () {
              = false;
              = false;
         }
 
         if () {
             return;
         }
    
         if (!) {
              = false;
              = null;
              = null;
              = null;
             if (isMonitoringEnabled()) {
                 .getRequestProcessor().setWorkerThreadID(0);
                         .getRequestProcessor());
             }
              = null;
         } else {
             .recycle();
             .recycle();
         }
 
         // Recycle ssl info
          = null;
     }
    

    
Notify the TaskListener that the request has been fully processed.
 
     public void terminateProcess(){
         if (  ) {
             .setStatus(.);
         } else {
             .setStatus(.);
         }
         fireTaskEvent(); 
     }
     
     
     // -------------------------------------------------------------------- //
     
    
    
Process pipelined HTTP requests using the specified input and output streams.

Parameters:
input stream from which the HTTP requests will be read
output stream which will be used to output the HTTP responses
Returns:
true if the connection needs to be keep-alived.
Throws:
java.lang.Exception error during an I/O operation
 
     public boolean process(InputStream inputOutputStream output)
             throws Exception {
                 
         preProcess(input,output);    
         doProcess(input,output);
         postProcess(input,output);
         return ;
     }
    
    
    
Get the request URI associated with this processor.
 
     public String getRequestURI() {
         return .requestURI().toString();
     }
     
 
     // ----------------------------------------------------- ActionHook Methods
 

    
Send an action to the connector.

Parameters:
actionCode Type of the action
param Action parameter
 
     public void action(ActionCode actionCodeObject param) {
 
         if (actionCode == .) {
             // Commit current response
             if (.isLoggable()) {
 //                LOGGER.log(LOG_LEVEL, "DefaultProcessorTask.ACTION_COMMIT dpt={0} isCommitted={1}",
 //                        new Object[]{this, response.isCommitted()});
                 .log("DefaultProcessorTask.ACTION_COMMIT dpt=" + this +
                         " isCommitted=" + .isCommitted(), new Exception("Stacktrace"));
             }
             if (.isCommitted())
                 return;
                         
             // Validate and write response headers
             prepareResponse();
             try {
                 .commit();
             } catch (IOException ex) {
                 SelectorThread.logger().log(.,
                         "processorTask.nonBlockingError"ex);               
                 // Set error flag
                  = true;
             }
 
         } else if (actionCode == .) {
 
             // Acknowlege request
 
             // Send a 100 status back if it makes sense (response not committed
             // yet, and client specified an expectation for 100-continue)
 
             if ((.isCommitted()) || (!))
                 return;
 
             MessageBytes expectMB = .getMimeHeaders().getValue("expect");
             if ((expectMB != null)
                 && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
                 try {
                     .sendAck();
                 } catch (IOException e) {
                     // Set error flag
                      = true;
                 }
             }
 
         } else if (actionCode == .) {
             // Close
 
             // End the processing of the current request, and stop any further
             // transactions with the client
 
             try {
                 .endRequest();
             } catch (IOException e) {
                SelectorThread.logger().log(.,
                        "processorTask.nonBlockingError"e);
                // Set error flag
                 = true;
            }
            if ( != null) {
                try {
                    ((SocketChannelOutputBuffer).flushBuffer();
                } catch (IOException ioe) {
                    if(SelectorThread.logger().isLoggable(.))
                    SelectorThread.logger().log(."ACTION_POST_REQUEST"ioe);
                     = true;
                }
            }
        } else if (actionCode == .) {
            // Reset response
            // Note: This must be called before the response is committed
            .reset();
        } else if (actionCode == .) {
            // Do nothing
        } else if (actionCode == .) {
             = true;
        } else if (actionCode == .) {
             = false;
        } else if (actionCode == . ) {
            try {
                if ( != null) {
                    Object sslO = .getCipherSuite();
                    if (sslO != null)
                        .setAttribute
                            (.sslO);
                    sslO = .getPeerCertificateChain(false);
                    if (sslO != null)
                        .setAttribute
                            (.sslO);
                    sslO = .getKeySize();
                    if (sslO != null)
                        .setAttribute
                            (.sslO);
                    sslO = .getSessionId();
                    if (sslO != null)
                        .setAttribute
                            (.sslO);
                }
            } catch (Exception e) {
                SelectorThread.logger().log(.,
                        "processorTask.errorSSL" ,e);
            }
        } else if (actionCode == .) {
            if (( == null) && ( != null)) {
                InetAddress inetAddr = .getInetAddress();
                if (inetAddr != null) {
                     = inetAddr.getHostAddress();
                }   
            }
            .remoteAddr().setString();
        } else if (actionCode == .) {
            
            if (( == null) && ( != null)) {
                InetAddress inetAddr = .getLocalAddress();
                if (inetAddr != null) {
                     = inetAddr.getHostName();
                }
            }
            .localName().setString();
        } else if (actionCode == .) {
            
            if (( == null) && ( != null)) {
                InetAddress inetAddr = .getInetAddress();
                if (inetAddr != null) {
                     = inetAddr.getHostName();
                }
                
                if( == null) {
                    if( != null) {
                         = ;
                    } else { // all we can do is punt
                        .remoteHost().recycle();
                    }
                }
            }
            .remoteHost().setString();
            
        } else if (actionCode == .) {
                       
            if ( == null)
                = .getLocalAddress().getHostAddress();
            .localAddr().setString();
            
        } else if (actionCode == .) {
            
            if (( == -1 ) && ( !=null)) {
                 = .getPort(); 
            }    
            .setRemotePort();
        } else if (actionCode == .) {
            
            if (( == -1 ) && ( !=null)) {
                 = .getLocalPort(); 
            }            
            .setLocalPort();
       
        } else if (actionCode == .) {
            if != null) {
                /*
                 * Consume and buffer the request body, so that it does not
                 * interfere with the client's handshake messages
                 */
                InputFilter[] inputFilters = .getFilters();
                ((BufferedInputFilterinputFilters[.])
                    .setLimit();
                .addActiveFilter
                    (inputFilters[.]);
                try {
                    Object sslO = .getPeerCertificateChain(true);
                    ifsslO != null) {
                        .setAttribute
                            (.sslO);
                    }
                } catch (Exception e) {
                    SelectorThread.logger().log(.,
                            "processorTask.exceptionSSLcert",e);
                }
            }
        } else if ( actionCode == . ) { 
            if (.getStatus() == 200 &&  == 0){
                try{
                    .handle(,.);
                } catch(IOException ex){
                    SelectorThread.logger().log(.,
                            "Handler exception",ex);
                }
            }      
        } else if (actionCode == . ) { 
            if ( != null) {
                SocketChannelOutputBuffer channelOutputBuffer = 
                        ((SocketChannelOutputBuffer));
                try{
                    channelOutputBuffer.flush();
                } catch (IOException ex){
                    if (SelectorThread.logger().isLoggable(.)){
                        SelectorThread.logger().log(.,
                                "ACTION_CLIENT_FLUSH",ex); 
                    }
                     = true;
                    .setErrorException(ex);
                }
            } 
        }
    }
    // ------------------------------------------------------ Connector Methods


    
Set the associated adapter.

Parameters:
adapter the new adapter
    public void setAdapter(Adapter adapter) {
        this. = adapter;
    }


    
Get the associated adapter.

Returns:
the associated adapter
    public Adapter getAdapter() {
        return ;
    }
    // ------------------------------------------------------ Protected Methods
    void keepAlive(MimeHeaders headers){
         = true;
         = false;
         = false;
        if ( != null) {
            .scheme().setString("https");
        }
        MessageBytes protocolMB = .protocol();
        if (protocolMB.equals(.)) {
             = true;
            protocolMB.setString(.);
        } else if (protocolMB.equals(.)) {
             = false;
             = false;
            protocolMB.setString(.);
        } else if (protocolMB.equals("")) {
            // HTTP/0.9
             = true;
             = false;
             = false;
        } else {
            // Unsupported protocol
             = false;
             = true;
            // Send 505; Unsupported HTTP version
            .setStatus(505);
        }
        // Check connection header
        MessageBytes connectionValueMB = headers.getValue("connection");
        if (connectionValueMB != null) {
            ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
            if (findBytes(connectionValueBC.) != -1) {
                 = false;
                 = false;
            } else if (findBytes(connectionValueBC,
                                 .) != -1) {
                 = true;
                 = true;
            }
        }
    }

    
After reading the request headers, we have to setup the request filters.
    protected void prepareRequest() {
        MessageBytes methodMB = .method();
        if (methodMB.equals(.)) {
            methodMB.setString(.);
        } else if (methodMB.equals(.)) {
            methodMB.setString(.);
        }
        MimeHeaders headers = .getMimeHeaders();
        keepAlive(headers);
        // Check connection header
        MessageBytes connectionValueMB = headers.getValue("connection");
        if (connectionValueMB != null) {
            ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
            if (findBytes(connectionValueBC.) != -1) {
                 = false;
                 = false;
            } else if (findBytes(connectionValueBC
                                 .) != -1) {
                 = true;
                 = true;
            }
        }
        // Check user-agent header
        if (( != null) && (() || ())) {
            MessageBytes userAgentValueMB =  
                .getMimeHeaders().getValue("user-agent");
            // Check in the restricted list, and adjust the http11 
            // and keepAlive flags accordingly
            if (userAgentValueMB != null) {
                String userAgentValue = userAgentValueMB.toString();
                for (int i = 0; i < .i++) {
                    if ([i].equals(userAgentValue)) {
                         = false;
                         = false;
                    }
                }
            }
        }
        // Check for a full URI (including protocol://host:port/)
        ByteChunk uriBC = .requestURI().getByteChunk();
        if (uriBC.startsWithIgnoreCase("http", 0)) {
            int pos = uriBC.indexOf("://", 0, 3, 4);
            int uriBCStart = uriBC.getStart();
            int slashPos = -1;
            if (pos != -1) {