FileDocCategorySizeDatePackage
Http11Processor.javaAPI DocGlassfish v2 API47988Fri May 04 22:32:42 BST 2007org.apache.coyote.http11

Http11Processor

public class Http11Processor extends Object implements org.apache.coyote.Processor, org.apache.coyote.ActionHook
Processes HTTP requests.
author
Remy Maucherat

Fields Summary
protected org.apache.coyote.Adapter
adapter
Associated adapter.
protected org.apache.coyote.Request
request
Request object.
protected org.apache.coyote.Response
response
Response object.
protected InternalInputBuffer
inputBuffer
Input.
protected InternalOutputBuffer
outputBuffer
Output.
protected boolean
started
State flag.
protected boolean
error
Error flag.
protected boolean
keepAlive
Keep-alive.
protected boolean
http11
HTTP/1.1 flag.
protected boolean
http09
HTTP/0.9 flag.
protected boolean
contentDelimitation
Content delimitator for the request (if false, the connection will be closed at the end of the request).
protected String[]
restrictedUserAgents
List of restricted user agents.
protected static final com.sun.org.apache.commons.logging.Log
log
Logger.
protected int
maxKeepAliveRequests
Maximum number of Keep-Alive requests to honor.
protected org.apache.tomcat.util.net.SSLSupport
sslSupport
SSL information.
protected Socket
socket
Socket associated with the current connection.
protected String
remoteAddr
Remote Address associated with the current connection.
protected String
remoteHost
Remote Host associated with the current connection.
protected String
localName
Local Host associated with the current connection.
protected int
localPort
Local port to which the socket is connected
protected int
remotePort
Remote port to which the socket is connected
protected String
localAddr
The local Host address.
protected int
timeout
Maximum timeout on uploads.
protected boolean
disableUploadTimeout
Flag to disable setting a different time-out on uploads.
protected int
compressionLevel
Allowed compression level.
protected int
compressionMinSize
Minimum contentsize to make compression.
protected int
maxPostSize
Max post size.
protected String[]
noCompressionUserAgents
List of user agents to not use gzip with
protected String[]
compressableMimeTypes
List of MIMES which could be gzipped
protected char[]
hostNameC
Host name (used to avoid useless B2C conversion on the host name).
protected org.apache.tomcat.util.threads.ThreadPool
threadPool
private static final String
USE_KEEP_ALIVE
private boolean
useKeepAliveAlgorithm
private int
requestBufferSize
The input request buffer size.
Constructors Summary
public Http11Processor()
Default constructor.

        this(Constants.DEFAULT_HTTP_HEADER_BUFFER_SIZE);
    
public Http11Processor(int headerBufferSize)


        request = new Request();
        // START OF SJSAS PE 8.1 6172948
        //inputBuffer = new InternalInputBuffer(request, headerBufferSize);
        inputBuffer = new InternalInputBuffer(request, requestBufferSize);
        // END OF SJSAS PE 8.1 6172948

        request.setInputBuffer(inputBuffer);

        response = new Response();
        response.setHook(this);
        outputBuffer = new InternalOutputBuffer(response, headerBufferSize);
        response.setOutputBuffer(outputBuffer);
        request.setResponse(response);

        initializeFilters();


        // START OF SJSAS PE 8.1 5036984
        if (System.getProperty(USE_KEEP_ALIVE) != null) {
            useKeepAliveAlgorithm = 
                        Boolean.valueOf(
                            System.getProperty(USE_KEEP_ALIVE)).booleanValue();

            if (!useKeepAliveAlgorithm)
                log.warn("Keep Alive algorith will no be used"); 
        }
        // END OF SJSAS PE 8.1 5036984

    
Methods Summary
public voidaction(org.apache.coyote.ActionCode actionCode, java.lang.Object param)
Send an action to the connector.

param
actionCode Type of the action
param
param Action parameter


        if (actionCode == ActionCode.ACTION_COMMIT) {
            // Commit current response

            if (response.isCommitted())
                return;

            // Validate and write response headers
            prepareResponse();
            try {
                outputBuffer.commit();
            } catch (IOException e) {
                // Set error flag
                error = true;
            }

        } else if (actionCode == ActionCode.ACTION_ACK) {

            // Acknowlege request

            // Send a 100 status back if it makes sense (response not committed
            // yet, and client specified an expectation for 100-continue)

            if (response.isCommitted())
                return;

            MessageBytes expectMB = 
                request.getMimeHeaders().getValue("expect");
            if ((expectMB != null)
                && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
                try {
                    outputBuffer.sendAck();
                } catch (IOException e) {
                    // Set error flag
                    error = true;
                    response.setErrorException(e);
                }
            }

        } else if (actionCode == ActionCode.ACTION_CLOSE) {
            // Close

            // End the processing of the current request, and stop any further
            // transactions with the client

            try {
                outputBuffer.endRequest();
            } catch (IOException e) {
                // Set error flag
                error = true;
            }

        } else if (actionCode == ActionCode.ACTION_RESET) {

            // Reset response

            // Note: This must be called before the response is committed

            outputBuffer.reset();

        } else if (actionCode == ActionCode.ACTION_CUSTOM) {

            // Do nothing

        } else if (actionCode == ActionCode.ACTION_START) {

            started = true;

        } else if (actionCode == ActionCode.ACTION_STOP) {

            started = false;

        } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) {

            try {
                if (sslSupport != null) {
                    Object sslO = sslSupport.getCipherSuite();
                    if (sslO != null)
                        request.setAttribute
                            (SSLSupport.CIPHER_SUITE_KEY, sslO);
                    sslO = sslSupport.getPeerCertificateChain(false);
                    if (sslO != null)
                        request.setAttribute
                            (SSLSupport.CERTIFICATE_KEY, sslO);
                    sslO = sslSupport.getKeySize();
                    if (sslO != null)
                        request.setAttribute
                            (SSLSupport.KEY_SIZE_KEY, sslO);
                    sslO = sslSupport.getSessionId();
                    if (sslO != null)
                        request.setAttribute
                            (SSLSupport.SESSION_ID_KEY, sslO);
                }
            } catch (Exception e) {
                log.warn("Exception getting SSL attributes " ,e);
            }

        } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) {

            if ((remoteAddr == null) && (socket != null)) {
                InetAddress inetAddr = socket.getInetAddress();
                remoteAddr = inetAddr.getHostAddress();
                request.remoteAddr().setString(remoteAddr);
            }

        } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) {

            if ((localName == null) && (socket != null)) {
                InetAddress inetAddr = socket.getLocalAddress();
                if (inetAddr != null) {
                    localName = inetAddr.getHostName();
                }
            }
            request.localName().setString(localName);

        } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) {

            if ((remoteHost == null) && (socket != null)) {
                InetAddress inetAddr = socket.getInetAddress();
                if (inetAddr != null) {
                    remoteHost = inetAddr.getHostName();
                }
            }
            request.remoteHost().setString(remoteHost);

        } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) {

            if (localAddr == null)
               localAddr = socket.getLocalAddress().getHostAddress();

            request.localAddr().setString(localAddr);

        } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) {

            if ((remotePort == -1 ) && (socket !=null)) {
                remotePort = socket.getPort();
            }
            request.setRemotePort(remotePort);

        } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) {

            if ((localPort == -1 ) && (socket !=null)) {
                localPort = socket.getLocalPort();
            }
            request.setLocalPort(localPort);

        } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) {
            if( sslSupport != null) {
                /*
                 * Consume and buffer the request body, so that it does not
                 * interfere with the client's handshake messages
                 */
                InputFilter[] inputFilters = inputBuffer.getFilters();
                ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER])
                    .setLimit(maxPostSize);
                inputBuffer.addActiveFilter
                    (inputFilters[Constants.BUFFERED_FILTER]);
                try {
                    Object sslO = sslSupport.getPeerCertificateChain(true);
                    if( sslO != null) {
                        request.setAttribute
                            (SSLSupport.CERTIFICATE_KEY, sslO);
                    }
                } catch (Exception e) {
                    log.warn("Exception getting SSL Cert",e);
                }
            }
        }

    
public voidaddCompressableMimeType(java.lang.String mimeType)
Add a mime-type which will be compressable The mime-type String will be exactly matched in the response mime-type header .

param
userAgent user-agent string

    	addStringArray(compressableMimeTypes, mimeType);
    
protected voidaddFilter(java.lang.String className)
Add input or output filter.

param
className class name of the filter

        try {
            Class clazz = Class.forName(className);
            Object obj = clazz.newInstance();
            if (obj instanceof InputFilter) {
                inputBuffer.addFilter((InputFilter) obj);
            } else if (obj instanceof OutputFilter) {
                outputBuffer.addFilter((OutputFilter) obj);
            } else {
                // Not a valid filter: log and ignore
            }
        } catch (Exception e) {
            // Log and ignore
        }
    
protected booleanaddInputFilter(InputFilter[] inputFilters, java.lang.String encodingName)
Add an input filter to the current request.

return
false if the encoding was not found (which would mean it is unsupported)

        if (encodingName.equals("identity")) {
            // Skip
        } else if (encodingName.equals("chunked")) {
            inputBuffer.addActiveFilter
                (inputFilters[Constants.CHUNKED_FILTER]);
            contentDelimitation = true;
        } else {
            for (int i = 2; i < inputFilters.length; i++) {
                if (inputFilters[i].getEncodingName()
                    .toString().equals(encodingName)) {
                    inputBuffer.addActiveFilter(inputFilters[i]);
                    return true;
                }
            }
            return false;
        }
        return true;
    
public voidaddNoCompressionUserAgent(java.lang.String userAgent)
Add user-agent for which gzip compression didn't works The user agent String given will be exactly matched to the user-agent header submitted by the client.

param
userAgent user-agent string

    	addStringArray(noCompressionUserAgents, userAgent);
    
public voidaddRestrictedUserAgent(java.lang.String userAgent)
Add restricted user-agent (which will downgrade the connector to HTTP/1.0 mode). The user agent String given will be exactly matched to the user-agent header submitted by the client.

param
userAgent user-agent string

    	addStringArray(restrictedUserAgents, userAgent);
    
private voidaddStringArray(java.lang.String[] sArray, java.lang.String value)
General use method

param
sArray the StringArray
param
value string

        if (sArray == null)
            sArray = new String[0];
        String[] results = new String[sArray.length + 1];
        for (int i = 0; i < sArray.length; i++)
            results[i] = sArray[i];
        results[sArray.length] = value;
        sArray = results;
    
protected intfindBytes(org.apache.tomcat.util.buf.ByteChunk bc, byte[] b)
Specialized utility method: find a sequence of lower case bytes inside a ByteChunk.


        byte first = b[0];
        byte[] buff = bc.getBuffer();
        int start = bc.getStart();
        int end = bc.getEnd();

	// Look for first char 
	int srcEnd = b.length;
        
	for (int i = start; i <= (end - srcEnd); i++) {
	    if (Ascii.toLower(buff[i]) != first) continue;
	    // found first char, now look for a match
            int myPos = i+1;
	    for (int srcPos = 1; srcPos < srcEnd; ) {
                if (Ascii.toLower(buff[myPos++]) != b[srcPos++])
		    break;
                if (srcPos == srcEnd) return i - start; // found it
	    }
	}
	return -1;

    
public java.lang.String[]findCompressableMimeTypes()
Return the list of restricted user agents.

        return (compressableMimeTypes);
    
public java.lang.String[]findNoCompressionUserAgents()
Return the list of no compression user agents.

        return (noCompressionUserAgents);
    
public java.lang.String[]findRestrictedUserAgents()
Return the list of restricted user agents.

        return (restrictedUserAgents);
    
public org.apache.coyote.AdaptergetAdapter()
Get the associated adapter.

return
the associated adapter

        return adapter;
    
public intgetBufferSize()
Return the request input buffer size

        return requestBufferSize;
    
public java.lang.StringgetCompression()
Return compression level.

    // END OF SJSAS PE 8.1 6172948

    // ------------------------------------------------------------- Properties


            
       
        switch (compressionLevel) {
        case 0:
            return "off";
        case 1:
            return "on";
        case 2:
            return "force";
        }
        return "off";
    
public booleangetDisableUploadTimeout()
Get the flag that controls upload time-outs.

        return disableUploadTimeout;
    
public intgetMaxKeepAliveRequests()
Return the number of Keep-Alive requests that we will honor.

        return maxKeepAliveRequests;
    
public intgetMaxPostSize()
Return the maximum size of a POST which will be buffered in SSL mode.

        return maxPostSize;
    
public org.apache.coyote.RequestgetRequest()
Get the request associated with this processor.

return

        return request;
    
public intgetTimeout()
Get the upload timeout.

        return timeout;
    
private booleaninStringArray(java.lang.String[] sArray, java.lang.String value)
General use method

param
sArray the StringArray
param
value string

        for (int i = 0; i < sArray.length; i++) {
            if (sArray[i].equals(value)) {
                return true;
            }
        }
        return false;
    
protected voidinitializeFilters()
Initialize standard input and output filters.


        // Create and add the identity filters.
        inputBuffer.addFilter(new IdentityInputFilter());
        outputBuffer.addFilter(new IdentityOutputFilter());

        // Create and add the chunked filters.
        inputBuffer.addFilter(new ChunkedInputFilter());
        outputBuffer.addFilter(new ChunkedOutputFilter());

        // Create and add the void filters.
        inputBuffer.addFilter(new VoidInputFilter());
        outputBuffer.addFilter(new VoidOutputFilter());

        // Create and add buffered input filter
        inputBuffer.addFilter(new BufferedInputFilter());

        // Create and add the chunked filters.
        //inputBuffer.addFilter(new GzipInputFilter());
        outputBuffer.addFilter(new GzipOutputFilter());
    
private booleanisCompressable()

        // Compression only since HTTP 1.1
        if (! http11)
            return false;

        // Check if browser support gzip encoding
        MessageBytes acceptEncodingMB = 
            request.getMimeHeaders().getValue("accept-encoding");
            
        if ((acceptEncodingMB == null) 
            || (acceptEncodingMB.indexOf("gzip") == -1))
            return false;

        // Check if content is not allready gzipped
        MessageBytes contentEncodingMB =
            response.getMimeHeaders().getValue("Content-Encoding");

        if ((contentEncodingMB != null) 
            && (contentEncodingMB.indexOf("gzip") != -1))
            return false;

        // If force mode, allways compress (test purposes only)
        if (compressionLevel == 2)
           return true;

        // Check for incompatible Browser
        if (noCompressionUserAgents != null) {
            MessageBytes userAgentValueMB =  
                request.getMimeHeaders().getValue("user-agent");
            String userAgentValue = userAgentValueMB.toString();

        	if (inStringArray(noCompressionUserAgents, userAgentValue))
        		return false;
        }

        // Check if suffisant len to trig the compression        
        int contentLength = response.getContentLength();
        if ((contentLength == -1) 
            || (contentLength > compressionMinSize)) {
            // Check for compatible MIME-TYPE
            if (compressableMimeTypes != null)
                return (inStringArray(compressableMimeTypes, response.getContentType()));
        }

		return false;
	
public voidparseHost(org.apache.tomcat.util.buf.MessageBytes valueMB)
Parse host.


        if (valueMB == null || valueMB.isNull()) {
            // HTTP/1.0
            // Default is what the socket tells us. Overriden if a host is 
            // found/parsed
            request.setServerPort(socket.getLocalPort());
            InetAddress localAddress = socket.getLocalAddress();
            // Setting the socket-related fields. The adapter doesn't know 
            // about socket.
            request.setLocalHost(localAddress.getHostName());
            request.serverName().setString(localAddress.getHostName());
            return;
        }

        ByteChunk valueBC = valueMB.getByteChunk();
        byte[] valueB = valueBC.getBytes();
        int valueL = valueBC.getLength();
        int valueS = valueBC.getStart();
        int colonPos = -1;
        if (hostNameC.length < valueL) {
            hostNameC = new char[valueL];
        }

        boolean ipv6 = (valueB[valueS] == '[");
        boolean bracketClosed = false;
        for (int i = 0; i < valueL; i++) {
            char b = (char) valueB[i + valueS];
            hostNameC[i] = b;
            if (b == ']") {
                bracketClosed = true;
            } else if (b == ':") {
                if (!ipv6 || bracketClosed) {
                    colonPos = i;
                    break;
                }
            }
        }

        if (colonPos < 0) {
            if (sslSupport == null) {
                // 80 - Default HTTTP port
                request.setServerPort(80);
            } else {
                // 443 - Default HTTPS port
                request.setServerPort(443);
            }
            request.serverName().setChars(hostNameC, 0, valueL);
        } else {

            request.serverName().setChars(hostNameC, 0, colonPos);

            int port = 0;
            int mult = 1;
            for (int i = valueL - 1; i > colonPos; i--) {
                int charValue = HexUtils.DEC[(int) valueB[i + valueS]];
                if (charValue == -1) {
                    // Invalid character
                    error = true;
                    // 400 - Bad request
                    response.setStatus(400);
                    break;
                }
                port = port + (charValue * mult);
                mult = 10 * mult;
            }
            request.setServerPort(port);

        }

    
protected voidprepareRequest()
After reading the request headers, we have to setup the request filters.


        http11 = true;
        http09 = false;
        contentDelimitation = false;
        if (sslSupport != null) {
            request.scheme().setString("https");
        }
        MessageBytes protocolMB = request.protocol();
        if (protocolMB.equals(Constants.HTTP_11)) {
            http11 = true;
            protocolMB.setString(Constants.HTTP_11);
        } else if (protocolMB.equals(Constants.HTTP_10)) {
            http11 = false;
            keepAlive = false;
            protocolMB.setString(Constants.HTTP_10);
        } else if (protocolMB.equals("")) {
            // HTTP/0.9
            http09 = true;
            http11 = false;
            keepAlive = false;
        } else {
            // Unsupported protocol
            http11 = false;
            error = true;
            // Send 505; Unsupported HTTP version
            response.setStatus(505);
        }

        MessageBytes methodMB = request.method();
        if (methodMB.equals(Constants.GET)) {
            methodMB.setString(Constants.GET);
        } else if (methodMB.equals(Constants.POST)) {
            methodMB.setString(Constants.POST);
        }

        // Check connection header
        MessageBytes connectionValueMB = 
            request.getMimeHeaders().getValue("connection");
        if (connectionValueMB != null) {
            ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
            if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) {
                keepAlive = false;
            } else if (findBytes(connectionValueBC, 
                                 Constants.KEEPALIVE_BYTES) != -1) {
                keepAlive = true;
            }
        }

        // Check user-agent header
        if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) {
            MessageBytes userAgentValueMB =  
                request.getMimeHeaders().getValue("user-agent");
            // Check in the restricted list, and adjust the http11 
            // and keepAlive flags accordingly
            String userAgentValue = userAgentValueMB.toString();
            for (int i = 0; i < restrictedUserAgents.length; i++) {
                if (restrictedUserAgents[i].equals(userAgentValue)) {
                    http11 = false;
                    keepAlive = false;
                }
            }
        }

        // Check for a full URI (including protocol://host:port/)
        ByteChunk uriBC = request.requestURI().getByteChunk();
        if (uriBC.startsWithIgnoreCase("http", 0)) {

            int pos = uriBC.indexOf("://", 0, 3, 4);
            int uriBCStart = uriBC.getStart();
            int slashPos = -1;
            if (pos != -1) {
                byte[] uriB = uriBC.getBytes();
                slashPos = uriBC.indexOf('/", pos + 3);
                if (slashPos == -1) {
                    slashPos = uriBC.getLength();
                    // Set URI as "/"
                    request.requestURI().setBytes
                        (uriB, uriBCStart + pos + 1, 1);
                } else {
                    request.requestURI().setBytes
                        (uriB, uriBCStart + slashPos, 
                         uriBC.getLength() - slashPos);
                }
                MessageBytes hostMB = 
                    request.getMimeHeaders().setValue("host");
                hostMB.setBytes(uriB, uriBCStart + pos + 3, 
                                slashPos - pos - 3);
            }

        }

        // Input filter setup
        InputFilter[] inputFilters = inputBuffer.getFilters();

        // Parse content-length header
        long contentLength = request.getContentLengthLong();
        if (contentLength >= 0) {
            inputBuffer.addActiveFilter
                (inputFilters[Constants.IDENTITY_FILTER]);
            contentDelimitation = true;
        }

        // Parse transfer-encoding header
        MessageBytes transferEncodingValueMB = null;
        if (http11)
            transferEncodingValueMB = 
                request.getMimeHeaders().getValue("transfer-encoding");
        if (transferEncodingValueMB != null) {
            String transferEncodingValue = transferEncodingValueMB.toString();
            // Parse the comma separated list. "identity" codings are ignored
            int startPos = 0;
            int commaPos = transferEncodingValue.indexOf(',");
            String encodingName = null;
            while (commaPos != -1) {
                encodingName = transferEncodingValue.substring
                    (startPos, commaPos).toLowerCase().trim();
                if (!addInputFilter(inputFilters, encodingName)) {
                    // Unsupported transfer encoding
                    error = true;
                    // 501 - Unimplemented
                    response.setStatus(501);
                }
                startPos = commaPos + 1;
                commaPos = transferEncodingValue.indexOf(',", startPos);
            }
            encodingName = transferEncodingValue.substring(startPos)
                .toLowerCase().trim();
            if (!addInputFilter(inputFilters, encodingName)) {
                // Unsupported transfer encoding
                error = true;
                // 501 - Unimplemented
                response.setStatus(501);
            }
        }

        MessageBytes valueMB = request.getMimeHeaders().getValue("host");

        // Check host header
        if (http11 && (valueMB == null)) {
            error = true;
            // 400 - Bad request
            response.setStatus(400);
        }

        parseHost(valueMB);

        if (!contentDelimitation) {
            // If there's no content length and we're using keep-alive 
            // (HTTP/1.0 with keep-alive or HTTP/1.1), assume
            // the client is not broken and didn't send a body
            if (keepAlive) {
                inputBuffer.addActiveFilter
                    (inputFilters[Constants.VOID_FILTER]);
                contentDelimitation = true;
            }
        }

        if (!contentDelimitation)
            keepAlive = false;

    
protected voidprepareResponse()
When committing the response, we have to validate the set of headers, as well as setup the response filters.


        boolean entityBody = true;
        contentDelimitation = false;

        OutputFilter[] outputFilters = outputBuffer.getFilters();

        if (http09 == true) {
            // HTTP/0.9
            outputBuffer.addActiveFilter
                (outputFilters[Constants.IDENTITY_FILTER]);
            return;
        }

        int statusCode = response.getStatus();
        if ((statusCode == 204) || (statusCode == 205) 
            || (statusCode == 304)) {
            // No entity body
            outputBuffer.addActiveFilter
                (outputFilters[Constants.VOID_FILTER]);
            entityBody = false;
            contentDelimitation = true;
        }

        MessageBytes methodMB = request.method();
        if (methodMB.equals("HEAD")) {
            // No entity body
            outputBuffer.addActiveFilter
                (outputFilters[Constants.VOID_FILTER]);
            contentDelimitation = true;
        }

        // Check for compression
        boolean useCompression = false;
        if (entityBody && (compressionLevel > 0)) {
            useCompression = isCompressable();
            
            // Change content-length to -1 to force chunking
            if (useCompression) {
                response.setContentLength(-1);
            }
        }

        MimeHeaders headers = response.getMimeHeaders();
        if (!entityBody) {
            response.setContentLength(-1);
        } else {
            String contentType = response.getContentType();
            if (contentType != null) {
                headers.setValue("Content-Type").setString(contentType);
            }
            String contentLanguage = response.getContentLanguage();
            if (contentLanguage != null) {
                headers.setValue("Content-Language")
                    .setString(contentLanguage);
            }
        }

        int contentLength = response.getContentLength();
        if (contentLength != -1) {
            response.getMimeHeaders().setValue("Content-Length")
                .setInt(contentLength);
            outputBuffer.addActiveFilter
                (outputFilters[Constants.IDENTITY_FILTER]);
            contentDelimitation = true;
        } else {
            if (entityBody && http11) {
                outputBuffer.addActiveFilter
                    (outputFilters[Constants.CHUNKED_FILTER]);
                contentDelimitation = true;
                response.addHeader("Transfer-Encoding", "chunked");
            }
        }

        if (useCompression) {
            outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
            // FIXME: Make content-encoding generation dynamic
            response.setHeader("Content-Encoding", "gzip");
            // Make Proxies happy via Vary (from mod_deflate)
            response.setHeader("Vary", "Accept-Encoding");
        }

        // Add date header
        if (! response.containsHeader("Date"))
          response.addHeader("Date", FastHttpDateFormat.getCurrentDate());

        // Add server header
        /* SJSAS 5022949
        response.addHeader("Server", Constants.SERVER);
         */
        // START SJSAS 5022949
        //response.addHeader("Server", ServerInfo.getServerInfo());
        // END SJSAS 5022949
        // START SJSAS 6415934
        response.addHeader("Server", System.getProperty("product.name"));
        // END SJSAS 6415934

        // Add transfer encoding header
        // FIXME

        if ((entityBody) && (!contentDelimitation)) {
            // Mark as close the connection after the request, and add the 
            // connection: close header
            keepAlive = false;
        }

        // If we know that the request is bad this early, add the
        // Connection: close header.
        keepAlive = keepAlive && !statusDropsConnection(statusCode);
        if (!keepAlive) {
            response.addHeader("Connection", "close");
        } else if (!http11) {
            response.addHeader("Connection", "Keep-Alive");
        }

        // Build the response header
        outputBuffer.sendStatus();

        int size = headers.size();
        for (int i = 0; i < size; i++) {
            outputBuffer.sendHeader(headers.getName(i), headers.getValue(i));
        }
        outputBuffer.endHeaders();

    
public booleanprocess(java.io.InputStream input, java.io.OutputStream output)
Process pipelined HTTP requests using the specified input and output streams.

param
input stream from which the HTTP requests will be read
param
output stream which will be used to output the HTTP responses
throws
IOException error during an I/O operation

    // END OF SJSAS 6231069
        ThreadWithAttributes thrA=
                (ThreadWithAttributes)Thread.currentThread();
        RequestInfo rp = request.getRequestProcessor();
        thrA.setCurrentStage(threadPool, "parsing http request");
        rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);

        // Set the remote address
        remoteAddr = null;
        remoteHost = null;
        localAddr = null;
        remotePort = -1;

        // Setting up the I/O
        inputBuffer.setInputStream(input);
        outputBuffer.setOutputStream(output);

        // Error flag
        error = false;
        keepAlive = true;

        int keepAliveLeft = maxKeepAliveRequests;
        int soTimeout = socket.getSoTimeout();

        // START OF SJSAS PE 8.1 5036984
        if ( useKeepAliveAlgorithm ) {
        // END OF SJSAS PE 8.1 5036984
            float threadRatio = 
                (float) threadPool.getCurrentThreadsBusy() 
                / (float) threadPool.getMaxThreads();
            if ((threadRatio > 0.33) && (threadRatio <= 0.66)) {
                soTimeout = soTimeout / 2;
            } else if (threadRatio > 0.66) {
                soTimeout = soTimeout / 5;
                keepAliveLeft = 1;
            }
        // START OF SJSAS PE 8.1 5036984
        }
        // END OF SJSAS PE 8.1 5036984

        boolean keptAlive = false;

        while (started && !error && keepAlive) {
            try {
                if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) {
                    socket.setSoTimeout(soTimeout);
                }
                inputBuffer.parseRequestLine();
                request.setStartTime(System.currentTimeMillis());
                thrA.setParam( threadPool, request.requestURI() );
                keptAlive = true;
                if (!disableUploadTimeout) {
                    socket.setSoTimeout(timeout);
                }
                inputBuffer.parseHeaders();
            } catch (IOException e) {
                error = true;
                break;
            } catch (Exception e) {
                log.debug("Error parsing HTTP request", e);
                // 400 - Bad Request
                response.setStatus(400);
                error = true;
            }

            // Setting up filters, and parse some request headers
            thrA.setCurrentStage(threadPool, "prepareRequest");
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
            try {
                prepareRequest();
            } catch (Throwable t) {
                log.debug("Error preparing request", t);
                // 400 - Internal Server Error
                response.setStatus(400);
                error = true;
            }

            // START OF SJSAS PE 8.1 5036984
            if ( useKeepAliveAlgorithm ) {
            // END OF SJSAS PE 8.1 5036984
                if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0)
                    keepAlive = false;
            // START OF SJSAS PE 8.1 5036984
            } else {
                keepAlive = false;
            }
            // END OF SJSAS PE 8.1 5036984

            // Process the request in the adapter
            if (!error) {
                try {
                    thrA.setCurrentStage(threadPool, "service");
                    rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                    adapter.service(request, response);
                    
                    // START GlassFish Issue 798
                    adapter.afterService(request, response);
                    // END GlassFish Issue 798
                    
                    // 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(keepAlive && !error) { // Avoid checking twice.
                        error = response.getErrorException() != null ||
                                statusDropsConnection(response.getStatus());
                    }

                } catch (InterruptedIOException e) {
                    error = true;
                } catch (Throwable t) {
                    log.error("Error processing request", t);
                    // 500 - Internal Server Error
                    response.setStatus(500);
                    error = true;
                }
            }

            // Finish the handling of the request
            try {
                thrA.setCurrentStage(threadPool, "endRequestIB");
                rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
                inputBuffer.endRequest();
            } catch (IOException e) {
                error = true;
            } catch (Throwable t) {
                log.error("Error finishing request", t);
                // 500 - Internal Server Error
                response.setStatus(500);
                error = true;
            }
            try {
                thrA.setCurrentStage(threadPool, "endRequestOB");
                rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
                outputBuffer.endRequest();
            } catch (IOException e) {
                error = true;
            } catch (Throwable t) {
                log.error("Error finishing response", t);
                error = true;
            }

            thrA.setCurrentStage(threadPool, "ended");
            rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);

            // Don't reset the param - we'll see it as ended. Next request
            // will reset it
            // thrA.setParam(null);
            // Next request
            inputBuffer.nextRequest();
            outputBuffer.nextRequest();

        }

        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);

        // Recycle
        inputBuffer.recycle();
        outputBuffer.recycle();

        // Recycle ssl info
        sslSupport = null;
        
        return true;
    
public voidsetAdapter(org.apache.coyote.Adapter adapter)
Set the associated adapter.

param
adapter the new adapter

        this.adapter = adapter;
    
public voidsetBufferSize(int requestBufferSize)
Set the request input buffer size

        this.requestBufferSize = requestBufferSize;
    
public voidsetCompressableMimeType(java.lang.String[] compressableMimeTypes)
Set compressable mime-type list (this method is best when used with a large number of connectors, where it would be better to have all of them referenced a single array).

        this.compressableMimeTypes = compressableMimeTypes;
    
public voidsetCompression(java.lang.String compression)
Set compression level.

        if (compression.equals("on")) {
            this.compressionLevel = 1;
        } else if (compression.equals("force")) {
            this.compressionLevel = 2;
        } else if (compression.equals("off")) {
            this.compressionLevel = 0;
        } else {
            try {
                // Try to parse compression as an int, which would give the
                // minimum compression size
                compressionMinSize = Integer.parseInt(compression);
                this.compressionLevel = 1;
            } catch (Exception e) {
                this.compressionLevel = 0;
            }
        }
    
public voidsetDisableUploadTimeout(boolean isDisabled)
Set the flag to control upload time-outs.

        disableUploadTimeout = isDisabled;
    
public voidsetMaxKeepAliveRequests(int mkar)
Set the maximum number of Keep-Alive requests to honor. This is to safeguard from DoS attacks. Setting to a negative value disables the check.

        maxKeepAliveRequests = mkar;
    
public voidsetMaxPostSize(int mps)
Set the maximum size of a POST which will be buffered in SSL mode.

        maxPostSize = mps;
    
public voidsetNoCompressionUserAgents(java.lang.String[] noCompressionUserAgents)
Set no compression user agent list (this method is best when used with a large number of connectors, where it would be better to have all of them referenced a single array).

        this.noCompressionUserAgents = noCompressionUserAgents;
    
public voidsetRestrictedUserAgents(java.lang.String[] restrictedUserAgents)
Set restricted user agent list (this method is best when used with a large number of connectors, where it would be better to have all of them referenced a single array).

        this.restrictedUserAgents = restrictedUserAgents;
    
public voidsetSSLSupport(org.apache.tomcat.util.net.SSLSupport sslSupport)
Set the SSL information for this HTTP connection.

        this.sslSupport = sslSupport;
    
public voidsetSocket(java.net.Socket socket)
Set the socket associated with this HTTP connection.

        this.socket = socket;
    
public voidsetThreadPool(org.apache.tomcat.util.threads.ThreadPool threadPool)

        this.threadPool = threadPool;
    
public voidsetTimeout(int timeouts)
Set the upload timeout.

        timeout = timeouts ;
    
protected booleanstatusDropsConnection(int status)
Determine if we must drop the connection because of the HTTP status code. Use the same list of codes as Apache/httpd.

        return status == 400 /* SC_BAD_REQUEST */ ||
               status == 408 /* SC_REQUEST_TIMEOUT */ ||
               status == 411 /* SC_LENGTH_REQUIRED */ ||
               status == 413 /* SC_REQUEST_ENTITY_TOO_LARGE */ ||
               status == 414 /* SC_REQUEST_URI_TOO_LARGE */ ||
               status == 500 /* SC_INTERNAL_SERVER_ERROR */ ||
               status == 503 /* SC_SERVICE_UNAVAILABLE */ ||
               status == 501 /* SC_NOT_IMPLEMENTED */;