Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * JBoss, Home of Professional Open Source.
    * Copyright 2012 Red Hat, Inc., and individual contributors
    * as indicated by the @author tags.
    *
    * 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 org.apache.coyote.http11;
  
  import  java.nio.channels.CompletionHandler;
  import java.util.Locale;
  
Http11NioProcessor

Processes HTTP requests.

Created on Feb 22, 2012 at 3:00:29 PM

Author(s):
Nabil Benothman
  
  public class Http11NioProcessor extends Http11AbstractProcessor {

Input.
  
  	protected InternalNioInputBuffer inputBuffer = null;

Output.
  
  	protected InternalNioOutputBuffer outputBuffer = null;

Sendfile data.
  
  	protected NioEndpoint.SendfileData sendfileData = null;

Channel associated with the current connection.
  
  	protected NioChannel channel;

Associated endpoint.
  
  	protected NioEndpoint endpoint;

Create a new instance of Http11NioProcessor

Parameters:
headerBufferSize
endpoint
  
  	public Http11NioProcessor(int headerBufferSizeNioEndpoint endpoint) {
  
  		this. = endpoint;
 		 = new Request();
 		 = new InternalNioInputBuffer(thisheaderBufferSizeendpoint);
 		if (endpoint.getUseSendfile()) {
 		}
 
 		 = new Response();
 		 = new InternalNioOutputBuffer(thisheaderBufferSizeendpoint);
 		 = endpoint.getSSLEnabled();
 
 		// Cause loading of HexUtils
 		int foo = .[0];
 
 		// Cause loading of FastHttpDateFormat
 		FastHttpDateFormat.getCurrentDate();
 	}

Mark the start of processing
 
 	public void startProcessing() {
 		 = true;
 	}

Mark the end of processing
 
 	public void endProcessing() {
 		 = false;
 	}

Returns:
true if the input buffer is available
 
 	public boolean isAvailable() {
 	}

    

Returns:
true if the processor is not doing anything
 
     public boolean isProcessing() {
         return ;
     }

Add input or output filter.

Parameters:
className class name of the filter
 
 	protected void addFilter(String className) {
 		try {
 			Class<?> clazz = Class.forName(className);
 			Object obj = clazz.newInstance();
 			if (obj instanceof InputFilter) {
 			} else if (obj instanceof OutputFilter) {
 			} else {
 			}
 		} catch (Exception e) {
 		}
 	}

General use method

Parameters:
sArray the StringArray
value string
 
 	protected String[] addStringArray(String sArray[], String value) {
 		String[] result = null;
 		if (sArray == null) {
 			result = new String[1];
 			result[0] = value;
 		} else {
 			result = new String[sArray.length + 1];
 			System.arraycopy(sArray, 0, result, 0, sArray.length);
 			// for (int i = 0; i < sArray.length; i++)
 			// result[i] = sArray[i];
 			result[sArray.length] = value;
 		}
 		return result;
 	}

Parameters:
channel
 
 	private void setChannel(NioChannel channel) {
 		// Setting up the channel
 		this. = channel;
 		this..setChannel(channel);
 		this..setChannel(channel);
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see
 	 * org.apache.coyote.http11.Http11AbstractProcessor#event(org.apache.tomcat
 	 * .util.net.SocketStatus)
 	 */
 	public SocketState event(SocketStatus statusthrows IOException {
 
 		try {
 			// If processing a write event, must flush any leftover bytes first
 			if (status == .) {
 				// The write notification is now done
 				 = false;
 				// Allow convenient synchronous blocking writes
 			} else if (status == .) {
 				// The resume notification is now done
 				 = false;
 			} else if (status == .) {
 				// Set error flag right away
 				 = true;
 			}
 			 = !.event(status);
 		} catch (InterruptedIOException e) {
 			 = true;
 		} catch (Throwable t) {
 			// 500 - Internal Server Error
 			 = true;
 		}
 
 
 		if () {
 		} else if (!) {
 			boolean pipelined = .nextRequest();
 			return (pipelined || !) ? . : .;
 		} else {
 			return .;
 		}
 	}

Process pipelined HTTP requests using the specified input and output streams.

Parameters:
channel
Returns:
the process state
Throws:
IOException error during an I/O operation
 
 	public SocketState process(NioChannel channelthrows IOException {
 
 		this.reset();
 		// Setting up the channel
 		this.setChannel(channel);
 
 		int keepAliveLeft = ;
 		int soTimeout = .getSoTimeout();
 		boolean keptAlive = false;
 		boolean openChannel = false;
 
 		while (! &&  && !) {
 			// Parsing the request header
 			try {
 				if (! && keptAlive && soTimeout > 0) {
 					.setSoTimeout(soTimeout);
 				}
 
 				if (!.parseRequestLine(keptAlive)) {
 					// This means that no data is available right now
 					// (long keep-alive), so that the processor should be
 					// recycled and the method should return true
 					final NioChannel ch = channel;
 					// Perform an asynchronous read operation to wait for
 					// incoming data
 					ch.awaitRead(soTimeout.ch,
 							new CompletionHandler<IntegerNioChannel>() {
 
 								public void completed(Integer nBytesNioChannel attachment) {
 									if (nBytes < 0) {
 										// Reach the end of the stream
 										failed(nullattachment);
 									} else {
 										if (!.processChannel(attachmentnull)) {
 										    closeChannel(attachment);
 										}
 									}
 								}
 
 								public void failed(Throwable excNioChannel attachment) {
 									closeChannel(attachment);
 								}
 							});
 					openChannel = true;
 					break;
 				}
 
 				keptAlive = true;
 				if (! && soTimeout > 0) {
 					.setSoTimeout(soTimeout);
 				}
 			} catch (IOException e) {
 				 = true;
 				break;
 			} catch (Throwable t) {
 				// 400 - Bad Request
 				 = true;
 			}
 			// Setting up filters, and parse some request headers
 			try {
 			} catch (Throwable t) {
 				// 500 - Internal Server Error
 				 = true;
 			}
 
 			if ( > 0 && --keepAliveLeft == 0) {
 				 = false;
 			}
 
 			// Process the request in the adapter
 			if (!) {
 				try {
 					// 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.
 					}
 				} catch (InterruptedIOException e) {
 					 = true;
 				} catch (Throwable t) {
                     ..errorProcessingRequest(t);
 					// 500 - Internal Server Error
 					 = true;
 				}
 			}
 
 			// Finish the handling of the request
 			if () {
 				// If there is an unspecified error, the connection will be
 				// closed
 			}
 			if (!) {
 			}
 
 			// If there was an error, make sure the request is counted as
 			// and error, and update the statistics counter
 			if () {
 			}
 			boolean pipelined = false;
 			if (!) {
 				// Next request
 				pipelined = .nextRequest();
 			}
 
 			// Do sendfile as needed: add socket to sendfile and end
 			if ( != null && !) {
 					if (.getChannel() == null) {
 						 = true;
 					} else {
 						openChannel = true;
 					}
 					break;
 				}
 			}
 
 		}
 
 		if () {
 			if () {
 			} else {
 				return .;
 			}
 		} else {
 			return (openChannel) ? . : .;
 		}
 
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see org.apache.coyote.http11.Http11AbstractProcessor#endRequest()
 	 */
 	public void endRequest() {
 
 		// Finish the handling of the request
 		try {
 		} catch (IOException e) {
 			 = true;
 		} catch (Throwable t) {
 			// 500 - Internal Server Error
 			 = true;
 		}
 		try {
 		} catch (IOException e) {
 			 = true;
 		} catch (Throwable t) {
             ..errorFinishingResponse(t);
 			 = true;
 		}
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see org.apache.coyote.http11.Http11AbstractProcessor#recycle()
 	 */
 	public void recycle() {
 		this. = null;
 		super.recycle();
 	}

Commit the action

Parameters:
param
 
 	private void commit(Object param) {
 		if (!.isCommitted()) {
 			// Validate and write response headers
 			try {
 			} catch (IOException e) {
 				// Set error flag
 				 = true;
 			}
 		}
 	}

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

Parameters:
param
 
 	private void sendAck(Object param) {
 
 		if ((.isCommitted()) || !) {
 			return;
 		}
 
 		try {
 		} catch (Exception e) {
 			// Set error flag
 			 = true;
 		}
 	}

Flush the output buffer
 
 	private void flush() {
 		try {
 		} catch (IOException e) {
 			// Set error flag
 			 = true;
 		}
 	}

End the processing of the current request, and stop any further transactions with the client
 
 	private void close() {
 		 = false;
 		try {
 		} catch (IOException e) {
 			// Set error flag
 			 = true;
 		}
 	}

Close the specified channel without handling of possible exception

Parameters:
ch the channel to be closed
 
 	private void closeChannel(NioChannel ch) {
 	}

Get the remote host address
 
 	private void requestHostAddressAttr() {
 		if ( == null && ( != null)) {
 			try {
                         .getHostAddress();
 			} catch (Exception e) {
 			}
 		}
 	}

Request the local name attribute
 
 	private void requestLocalNameAttr() {
 		if ( == null && ( != null)) {
 			try {
 			} catch (Exception e) {
                 ..errorGettingSocketInformation(e);
 			}
 		}
 	}

Get remote host name
 
 	private void requestHostAttribute() {
 		if ( == null && ( != null)) {
 			try {
 				if ( == null) {
 				}
 			} catch (Exception e) {
                 ..errorGettingSocketInformation(e);
 			}
 		}
 	}

Get local host address
 
 	private void requestLocalHostAddressAttr() {
 		if ( == null && ( != null)) {
 			try {
 			} catch (Exception e) {
                 ..errorGettingSocketInformation(e);
 			}
 		}
 
 	}

Get remote port
 
 	private void requestRemotePortAttr() {
 		if ( == -1 && ( != null)) {
 			try {
 			} catch (Exception e) {
                 ..errorGettingSocketInformation(e);
 			}
 		}
 	}

Get local port
 
 	private void requestLocalPortAttr() {
 		if ( == -1 && ( != null)) {
 			try {
 			} catch (Exception e) {
                 ..errorGettingSocketInformation(e);
 			}
 		}
 	}

Get the SSL attribute
 
 	private void requestSSLAttr() {
 		try {
 			if ( != null) {
 				if (sslO != null)
 				if (sslO != null)
 				sslO = .getKeySize();
 				if (sslO != null)
 				if (sslO != null)
 			}
 		} catch (Exception e) {
 		}
 	}

Get the SSL certificate
 
 	private void requestSSLCertificate() {
 		if ( != null) {
 			// Consume and buffer the request body, so that it does not
 			// interfere with the client's handshake messages
 			if ( != 0) {
 				BufferedInputFilter buffredInputFilter = new BufferedInputFilter();
 				buffredInputFilter.setLimit();
 				.addActiveFilter(buffredInputFilter);
 			}
 			try {
 				if (sslO != null) {
 				}
 			} catch (Exception e) {
 			}
 		}
 	}

Parameters:
param
 
 	private void requestSetBodyReplay(Object param) {
 		ByteChunk body = (ByteChunkparam;
 
 		InputFilter savedBody = new SavedRequestInputFilter(body);
 		savedBody.setRequest();
 
 		internalBuffer.addActiveFilter(savedBody);
 	}

Begin an event

Parameters:
param the vent parameter
 
 	private void beginEvent(Object param) {
 		 = true;
 		// Set channel to non blocking mode
 		if (param == .) {
 		}
 	}

End the event

Parameters:
param the event parameter
 
 	private void endEvent(Object param) {
 		 = false;
 		// End non blocking mode
 		}
 	}

Resume the event

Parameters:
param the vent parameter
 
 	private synchronized void resumeEvent(Object paramboolean read) {
 	    if (read) {
 	         = true;
 	    }
 		// An event is being processed already: adding for resume will be
 		// done
 		// when the channel gets back to the poller
         if (! && !) {
 			.addEventChannel(falsefalsetruetrue);
 		}
 	}

Write Event

Parameters:
param
 
 	private synchronized void writeEvent(Object param) {
 		// An event is being processed already: adding for write will be
 		// done
 		// when the channel gets back to the poller
 		if (! && !) {
 			.addEventChannel(falsetruefalsetrue);
 		}
 	}

Suspend Event
 
 	private void suspendEvent() {
 		 = false;
 	}

Timeout event

Parameters:
param the timeout value
 
 	private void timeoutEvent(Object param) {
 		 = ((Integerparam).intValue();
 	}

Make the input buffer available
 
 	private void makeAvailable() {
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see org.apache.coyote.ActionHook#action(org.apache.coyote.ActionCode,
 	 * java.lang.Object)
 	 */
 	public void action(ActionCode actionCodeObject param) {
 
 		if (actionCode == .) {
 			// Commit current response
 			commit(param);
 		} else if (actionCode == .) {
 			// Acknowledge request
 			sendAck(param);
 		} else if (actionCode == .) {
 			// Flush
 			flush();
 		} else if (actionCode == .) {
 			// Close
 			close();
 		} else if (actionCode == .) {
 			// DO NOTHING
 		} else if (actionCode == .) {
 			// Get remote host address
 		} else if (actionCode == .) {
 			// Get local host name
 		} else if (actionCode == .) {
 			// Get remote host name
 		} else if (actionCode == .) {
 			// Get local host address
 		} else if (actionCode == .) {
 			// Get remote port
 		} else if (actionCode == .) {
 			// Get local port
 		} else if (actionCode == .) {
 			// request for the SSL attribute
 		} else if (actionCode == .) {
 			// Request for the SSL certificate
 		} else if (actionCode == .) {
 			//
 		} else if (actionCode == .) {
 			// make the input buffer available
 		} else if (actionCode == .) {
 			// Begin event
 			beginEvent(param);
 		} else if (actionCode == .) {
 			// End event
 			endEvent(param);
 		} else if (actionCode == .) {
 			// Suspend event
 		} else if (actionCode == .) {
 			// Resume event
 			resumeEvent(paramtrue);
         } else if (actionCode == .) {
             // Resume event
             resumeEvent(paramfalse);
 		} else if (actionCode == .) {
 			// Write event
 			writeEvent(param);
 		} else if (actionCode == .) {
 			// Timeout event
 			timeoutEvent(param);
 		} else if (actionCode == .) {
 		    .setNonBlocking(true);
 		     = true;
 		} else if (actionCode == .) {
 	        .setWriteListener((WriteListenerparam);
 		    writeEvent(param);
 		} else if (actionCode == .) {
             // Switch to raw bytes mode
             .removeActiveFilters();
             .removeActiveFilters();
              = .;
         }
 	}
 
 	/*
 	 * (non-Javadoc)
 	 * 
 	 * @see org.apache.coyote.http11.Http11AbstractProcessor#prepareRequest()
 	 */
 	protected void prepareRequest() {
 
 		 = true;
 		 = false;
 		 = false;
 		 = null;
 
 		if () {
 			.scheme().setString("https");
 		}
 		MessageBytes protocolMB = .protocol();
 
 		if (protocolMB.equals(.)) {
 			 = true;
 		} else if (protocolMB.equals(.)) {
 			 = false;
 			 = false;
 		} else if (protocolMB.equals("")) {
 			// HTTP/0.9
 			 = true;
 			 = false;
 			 = false;
 		} else {
 			// Unsupported protocol
 			 = false;
 			 = true;
 			// Send 505; Unsupported HTTP version
 		}
 
 		MessageBytes methodMB = .method();
 		if (methodMB.equals(.)) {
 			methodMB.setString(.);
 		} else if (methodMB.equals(.)) {
 		}
 
 
 		// Check connection header
 		MessageBytes connectionValueMB = headers.getValue("connection");
 		if (connectionValueMB != null) {
 			ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
 			if (findBytes(connectionValueBC.) != -1) {
 				 = false;
 			} else if (findBytes(connectionValueBC.) != -1) {
 				 = true;
 			}
 		}
 
 		MessageBytes expectMB = null;
 		if ()
 			expectMB = headers.getValue("expect");
 		if ((expectMB != null) && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
 			 = true;
 		}
 
 		// Check user-agent header
 		if (( != null) && (() || ())) {
 			MessageBytes userAgentValueMB = headers.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].matcher(userAgentValue).matches()) {
 						 = false;
 						 = false;
 						break;
 					}
 				}
 			}
 		}
 
 		// Check for a full URI (including protocol://host:port/)
 		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 "/"
 					.requestURI().setBytes(uriBuriBCStart + pos + 1, 1);
 				} else {
 					.requestURI().setBytes(uriBuriBCStart + slashPos,
 							uriBC.getLength() - slashPos);
 				}
 				MessageBytes hostMB = headers.setValue("host");
 				hostMB.setBytes(uriBuriBCStart + pos + 3, slashPos - pos - 3);
 			}
 
 		}
 
 		// Input filter setup
 		InputFilter[] inputFilters = .getFilters();
 
 		// Parse transfer-encoding header
 		MessageBytes transferEncodingValueMB = null;
 		if ()
 			transferEncodingValueMB = headers.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(startPoscommaPos)
				if (!addInputFilter(inputFiltersencodingName)) {
					// Unsupported transfer encoding
					 = true;
					// 501 - Unimplemented
				startPos = commaPos + 1;
				commaPos = transferEncodingValue.indexOf(','startPos);
			encodingName = transferEncodingValue.substring(startPos).toLowerCase(.)
			if (!addInputFilter(inputFiltersencodingName)) {
				// Unsupported transfer encoding
				 = true;
				// 501 - Unimplemented
        // Parse content-length header
        long contentLength = .getContentLengthLong();
        if (contentLength >= 0) {
            if () {
                // contentDelimitation being true at this point indicates that
                // chunked encoding is being used but chunked encoding should
                // not be used with a content length. RFC 2616, section 4.4,
                // bullet 3 states Content-Length must be ignored in this case -
                // so remove it.
                headers.removeHeader("content-length");
                .setContentLength(-1);
            } else {
                .addActiveFilter(inputFilters[.]);
                 = true;
            }
        }
		MessageBytes valueMB = headers.getValue("host");
		// Check host header
		if ( && (valueMB == null)) {
			 = true;
			// 400 - Bad request
		parseHost(valueMB);
			// If there's no content length
			// (broken HTTP/1.0 or HTTP/1.1), assume
			// the client is not broken and didn't send a body
	}

Parse host.
	protected void parseHost(MessageBytes valueMB) {
		if (valueMB == null || valueMB.isNull()) {
			// HTTP/1.0
			// Default is what the socket tells us. Overriden if a host is
			// found/parsed
			return;
		ByteChunk valueBC = valueMB.getByteChunk();
		byte[] valueB = valueBC.getBytes();
		int valueL = valueBC.getLength();
		int valueS = valueBC.getStart();
		int colonPos = -1;
		if (. < valueL) {
			 = new char[valueL];
		boolean ipv6 = (valueB[valueS] == '[');
		boolean bracketClosed = false;
		for (int i = 0; i < valueLi++) {
			char b = (charvalueB[i + valueS];
			[i] = b;
			if (b == ']') {
				bracketClosed = true;
else if (b == ':') {
				if (!ipv6 || bracketClosed) {
					colonPos = i;
					break;
		if (colonPos < 0) {
			if (!) {
				// 80 - Default HTTP port
else {
				// 443 - Default HTTPS port
else {
			int port = 0;
			int mult = 1;
			for (int i = valueL - 1; i > colonPosi--) {
				int charValue = .[valueB[i + valueS] & 0xff];
				if (charValue == -1) {
					// Invalid character
					 = true;
					// 400 - Bad request
					break;
				port = port + (charValue * mult);
				mult = 10 * mult;
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.coyote.http11.Http11AbstractProcessor#prepareResponse()
	 */
	protected void prepareResponse() {
		boolean entityBody = true;
		OutputFilter[] outputFilters = .getFilters();
		if ( == true) {
			// HTTP/0.9
			return;
		int statusCode = .getStatus();
		if ((statusCode == 204) || (statusCode == 205) || (statusCode == 304)) {
			// No entity body
			entityBody = false;
        if (statusCode >= 100 && statusCode < 200) {
            entityBody = false;
             = true;
        }
		MessageBytes methodMB = .method();
		if (methodMB.equals("HEAD")) {
			// No entity body
		// Sendfile support
			// No entity body sent here
		// Check for compression