Author: markt
Date: Fri Jul  8 09:50:02 2011
New Revision: 1144225

URL: http://svn.apache.org/viewvc?rev=1144225&view=rev
Log:
Fix indentation

Modified:
    tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java

Modified: tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1144225&r1=1144224&r2=1144225&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Fri Jul  
8 09:50:02 2011
@@ -70,7 +70,7 @@ public abstract class AbstractAjpProcess
      * Flush message array.
      */
     protected static final byte[] flushMessageArray;
-    
+
 
     /**
      * Pong message array.
@@ -88,7 +88,7 @@ public abstract class AbstractAjpProcess
         endMessageArray = new byte[endMessage.getLen()];
         System.arraycopy(endMessage.getBuffer(), 0, endMessageArray, 0,
                 endMessage.getLen());
-        
+
         // Allocate the flush message array
         AjpMessage flushMessage = new AjpMessage(16);
         flushMessage.reset();
@@ -99,7 +99,7 @@ public abstract class AbstractAjpProcess
         flushMessageArray = new byte[flushMessage.getLen()];
         System.arraycopy(flushMessage.getBuffer(), 0, flushMessageArray, 0,
                 flushMessage.getLen());
-        
+
         // Allocate the pong message array
         AjpMessage pongMessage = new AjpMessage(16);
         pongMessage.reset();
@@ -110,7 +110,7 @@ public abstract class AbstractAjpProcess
                 0, pongMessage.getLen());
     }
 
-    
+
     // ----------------------------------------------------- Instance Variables
 
 
@@ -146,7 +146,7 @@ public abstract class AbstractAjpProcess
      */
     protected AjpMessage bodyMessage = null;
 
-    
+
     /**
      * Body message.
      */
@@ -205,28 +205,28 @@ public abstract class AbstractAjpProcess
      * Finished response.
      */
     protected boolean finished = false;
-    
-    
+
+
     /**
      * Bytes written to client for the current request
      */
     protected long byteCount = 0;
-    
-    
+
+
     // ------------------------------------------------------------ Constructor
-    
+
     public AbstractAjpProcessor(int packetSize, AbstractEndpoint endpoint) {
-        
+
         super(endpoint);
 
         this.packetSize = packetSize;
 
         request.setInputBuffer(new SocketInputBuffer());
-        
+
         requestHeaderMessage = new AjpMessage(packetSize);
         responseHeaderMessage = new AjpMessage(packetSize);
         bodyMessage = new AjpMessage(packetSize);
-        
+
         // Set the getBody message buffer
         AjpMessage getBodyMessage = new AjpMessage(16);
         getBodyMessage.reset();
@@ -237,10 +237,10 @@ public abstract class AbstractAjpProcess
         getBodyMessage.end();
         getBodyMessageArray = new byte[getBodyMessage.getLen()];
         System.arraycopy(getBodyMessage.getBuffer(), 0, getBodyMessageArray, 
-                         0, getBodyMessage.getLen());
+                0, getBodyMessage.getLen());
     }
 
-    
+
     // ------------------------------------------------------------- Properties
 
 
@@ -289,648 +289,648 @@ public abstract class AbstractAjpProcess
     // --------------------------------------------------------- Public Methods
 
 
-   /**
-    * Send an action to the connector.
-    *
-    * @param actionCode Type of the action
-    * @param param Action parameter
-    */
-   @Override
-   public final void action(ActionCode actionCode, Object param) {
-       
-       if (actionCode == ActionCode.COMMIT) {
-
-           if (response.isCommitted())
-               return;
-
-           // Validate and write response headers
-           try {
-               prepareResponse();
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-           try {
-               flush(false);
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-       } else if (actionCode == ActionCode.CLIENT_FLUSH) {
-
-           if (!response.isCommitted()) {
-               // Validate and write response headers
-               try {
-                   prepareResponse();
-               } catch (IOException e) {
-                   // Set error flag
-                   error = true;
-                   return;
-               }
-           }
-
-           try {
-               flush(true);
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-       } else if (actionCode == ActionCode.DISABLE_SWALLOW_INPUT) {
-           // TODO: Do not swallow request input but
-           // make sure we are closing the connection
-           error = true;
-
-       } else if (actionCode == ActionCode.CLOSE) {
-           // Close
-           // End the processing of the current request, and stop any further
-           // transactions with the client
-
-           try {
-               finish();
-           } catch (IOException e) {
-               // Set error flag
-               error = true;
-           }
-
-       } else if (actionCode == ActionCode.REQ_SSL_ATTRIBUTE ) {
-
-           if (!certificates.isNull()) {
-               ByteChunk certData = certificates.getByteChunk();
-               X509Certificate jsseCerts[] = null;
-               ByteArrayInputStream bais =
-                   new ByteArrayInputStream(certData.getBytes(),
-                           certData.getStart(),
-                           certData.getLength());
-               // Fill the  elements.
-               try {
-                   CertificateFactory cf;
-                   if (clientCertProvider == null) {
-                       cf = CertificateFactory.getInstance("X.509");
-                   } else {
-                       cf = CertificateFactory.getInstance("X.509",
-                               clientCertProvider);
-                   }
-                   while(bais.available() > 0) {
-                       X509Certificate cert = (X509Certificate)
-                           cf.generateCertificate(bais);
-                       if(jsseCerts == null) {
-                           jsseCerts = new X509Certificate[1];
-                           jsseCerts[0] = cert;
-                       } else {
-                           X509Certificate [] temp = new 
X509Certificate[jsseCerts.length+1];
-                           
System.arraycopy(jsseCerts,0,temp,0,jsseCerts.length);
-                           temp[jsseCerts.length] = cert;
-                           jsseCerts = temp;
-                       }
-                   }
-               } catch (java.security.cert.CertificateException e) {
-                   getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
-                   return;
-               } catch (NoSuchProviderException e) {
-                   getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
-                   return;
-               }
-               request.setAttribute(SSLSupport.CERTIFICATE_KEY, jsseCerts);
-           }
-
-       } else if (actionCode == ActionCode.REQ_HOST_ATTRIBUTE) {
-
-           // Get remote host name using a DNS resolution
-           if (request.remoteHost().isNull()) {
-               try {
-                   request.remoteHost().setString(InetAddress.getByName
-                           (request.remoteAddr().toString()).getHostName());
-               } catch (IOException iex) {
-                   // Ignore
-               }
-           }
-
-       } else if (actionCode == ActionCode.REQ_LOCAL_ADDR_ATTRIBUTE) {
-
-           // Copy from local name for now, which should simply be an address
-           request.localAddr().setString(request.localName().toString());
-
-       } else if (actionCode == ActionCode.REQ_SET_BODY_REPLAY) {
-
-           // Set the given bytes as the content
-           ByteChunk bc = (ByteChunk) param;
-           int length = bc.getLength();
-           bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
-           request.setContentLength(length);
-           first = false;
-           empty = false;
-           replay = true;
-
-       } else if (actionCode == ActionCode.ASYNC_START) {
-           asyncStateMachine.asyncStart((AsyncContextCallback) param);
-       } else if (actionCode == ActionCode.ASYNC_DISPATCHED) {
-           asyncStateMachine.asyncDispatched();
-       } else if (actionCode == ActionCode.ASYNC_TIMEOUT) {
-           AtomicBoolean result = (AtomicBoolean) param;
-           result.set(asyncStateMachine.asyncTimeout());
-       } else if (actionCode == ActionCode.ASYNC_RUN) {
-           asyncStateMachine.asyncRun((Runnable) param);
-       } else if (actionCode == ActionCode.ASYNC_ERROR) {
-           asyncStateMachine.asyncError();
-       } else if (actionCode == ActionCode.ASYNC_IS_STARTED) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsyncStarted());
-       } else if (actionCode == ActionCode.ASYNC_IS_DISPATCHING) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsyncDispatching());
-       } else if (actionCode == ActionCode.ASYNC_IS_ASYNC) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsync());
-       } else if (actionCode == ActionCode.ASYNC_IS_TIMINGOUT) {
-           ((AtomicBoolean) param).set(asyncStateMachine.isAsyncTimingOut());
-       }  else {
-           actionInternal(actionCode, param);
-       }
-   }
-   
-   // Methods called by action()
-   protected abstract void actionInternal(ActionCode actionCode, Object param);
-   protected abstract void flush(boolean tbd) throws IOException;
-   protected abstract void finish() throws IOException;
-   
-   
-   public SocketState asyncDispatch(SocketStatus status) {
-
-       RequestInfo rp = request.getRequestProcessor();
-       try {
-           rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
-           error = !adapter.asyncDispatch(request, response, status);
-       } catch (InterruptedIOException e) {
-           error = true;
-       } catch (Throwable t) {
-           ExceptionUtils.handleThrowable(t);
-           getLog().error(sm.getString("http11processor.request.process"), t);
-           error = true;
-       } finally {
-           if (error) {
-               // 500 - Internal Server Error
-               response.setStatus(500);
-               adapter.log(request, response, 0);
-           }
-       }
-
-       rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
-
-       if (isAsync()) {
-           if (error) {
-               request.updateCounters();
-               return SocketState.CLOSED;
-           } else {
-               return SocketState.LONG;
-           }
-       } else {
-           request.updateCounters();
-           if (error) {
-               return SocketState.CLOSED;
-           } else {
-               return SocketState.OPEN;
-           }
-       }
-   }
-
-   
-   public void recycle() {
-       asyncStateMachine.recycle();
-
-       // Recycle Request object
-       first = true;
-       endOfStream = false;
-       empty = true;
-       replay = false;
-       finished = false;
-       request.recycle();
-       response.recycle();
-       certificates.recycle();
-       byteCount = 0;
-   }
-   
-   // ------------------------------------------------------ Protected Methods
-
-
-   /**
-    * After reading the request headers, we have to setup the request filters.
-    */
-   protected void prepareRequest() {
-
-       // Translate the HTTP method code to a String.
-       byte methodCode = requestHeaderMessage.getByte();
-       if (methodCode != Constants.SC_M_JK_STORED) {
-           String methodName = Constants.getMethodForCode(methodCode - 1);
-           request.method().setString(methodName);
-       }
-
-       requestHeaderMessage.getBytes(request.protocol());
-       requestHeaderMessage.getBytes(request.requestURI());
-
-       requestHeaderMessage.getBytes(request.remoteAddr());
-       requestHeaderMessage.getBytes(request.remoteHost());
-       requestHeaderMessage.getBytes(request.localName());
-       request.setLocalPort(requestHeaderMessage.getInt());
-
-       boolean isSSL = requestHeaderMessage.getByte() != 0;
-       if (isSSL) {
-           request.scheme().setString("https");
-       }
-
-       // Decode headers
-       MimeHeaders headers = request.getMimeHeaders();
-
-       int hCount = requestHeaderMessage.getInt();
-       for(int i = 0 ; i < hCount ; i++) {
-           String hName = null;
-
-           // Header names are encoded as either an integer code starting
-           // with 0xA0, or as a normal string (in which case the first
-           // two bytes are the length).
-           int isc = requestHeaderMessage.peekInt();
-           int hId = isc & 0xFF;
-
-           MessageBytes vMB = null;
-           isc &= 0xFF00;
-           if(0xA000 == isc) {
-               requestHeaderMessage.getInt(); // To advance the read position
-               hName = Constants.getHeaderForCode(hId - 1);
-               vMB = headers.addValue(hName);
-           } else {
-               // reset hId -- if the header currently being read
-               // happens to be 7 or 8 bytes long, the code below
-               // will think it's the content-type header or the
-               // content-length header - SC_REQ_CONTENT_TYPE=7,
-               // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
-               // behaviour.  see bug 5861 for more information.
-               hId = -1;
-               requestHeaderMessage.getBytes(tmpMB);
-               ByteChunk bc = tmpMB.getByteChunk();
-               vMB = headers.addValue(bc.getBuffer(),
-                       bc.getStart(), bc.getLength());
-           }
-
-           requestHeaderMessage.getBytes(vMB);
-
-           if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
-                   (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
-               // just read the content-length header, so set it
-               long cl = vMB.getLong();
-               if(cl < Integer.MAX_VALUE)
-                   request.setContentLength( (int)cl );
-           } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
-                   (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
-               // just read the content-type header, so set it
-               ByteChunk bchunk = vMB.getByteChunk();
-               request.contentType().setBytes(bchunk.getBytes(),
-                       bchunk.getOffset(),
-                       bchunk.getLength());
-           }
-       }
-
-       // Decode extra attributes
-       boolean secret = false;
-       byte attributeCode;
-       while ((attributeCode = requestHeaderMessage.getByte())
-               != Constants.SC_A_ARE_DONE) {
-
-           switch (attributeCode) {
-
-           case Constants.SC_A_REQ_ATTRIBUTE :
-               requestHeaderMessage.getBytes(tmpMB);
-               String n = tmpMB.toString();
-               requestHeaderMessage.getBytes(tmpMB);
-               String v = tmpMB.toString();
-               /*
-                * AJP13 misses to forward the remotePort.
-                * Allow the AJP connector to add this info via
-                * a private request attribute.
-                * We will accept the forwarded data as the remote port,
-                * and remove it from the public list of request attributes.
-                */
-               if(n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
-                   try {
-                       request.setRemotePort(Integer.parseInt(v));
-                   } catch (NumberFormatException nfe) {
-                       // Ignore invalid value
-                   }
-               } else {
-                   request.setAttribute(n, v );
-               }
-               break;
-
-           case Constants.SC_A_CONTEXT :
-               requestHeaderMessage.getBytes(tmpMB);
-               // nothing
-               break;
-
-           case Constants.SC_A_SERVLET_PATH :
-               requestHeaderMessage.getBytes(tmpMB);
-               // nothing
-               break;
-
-           case Constants.SC_A_REMOTE_USER :
-               if (tomcatAuthentication) {
-                   // ignore server
-                   requestHeaderMessage.getBytes(tmpMB);
-               } else {
-                   requestHeaderMessage.getBytes(request.getRemoteUser());
-               }
-               break;
-
-           case Constants.SC_A_AUTH_TYPE :
-               if (tomcatAuthentication) {
-                   // ignore server
-                   requestHeaderMessage.getBytes(tmpMB);
-               } else {
-                   requestHeaderMessage.getBytes(request.getAuthType());
-               }
-               break;
-
-           case Constants.SC_A_QUERY_STRING :
-               requestHeaderMessage.getBytes(request.queryString());
-               break;
-
-           case Constants.SC_A_JVM_ROUTE :
-               requestHeaderMessage.getBytes(request.instanceId());
-               break;
-
-           case Constants.SC_A_SSL_CERT :
-               request.scheme().setString("https");
-               // SSL certificate extraction is lazy, moved to JkCoyoteHandler
-               requestHeaderMessage.getBytes(certificates);
-               break;
-
-           case Constants.SC_A_SSL_CIPHER :
-               request.scheme().setString("https");
-               requestHeaderMessage.getBytes(tmpMB);
-               request.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
-                                    tmpMB.toString());
-               break;
-
-           case Constants.SC_A_SSL_SESSION :
-               request.scheme().setString("https");
-               requestHeaderMessage.getBytes(tmpMB);
-               request.setAttribute(SSLSupport.SESSION_ID_KEY,
-                                    tmpMB.toString());
-               break;
-
-           case Constants.SC_A_SSL_KEY_SIZE :
-               request.setAttribute(SSLSupport.KEY_SIZE_KEY,
-                       Integer.valueOf(requestHeaderMessage.getInt()));
-               break;
-
-           case Constants.SC_A_STORED_METHOD:
-               requestHeaderMessage.getBytes(request.method());
-               break;
-
-           case Constants.SC_A_SECRET:
-               requestHeaderMessage.getBytes(tmpMB);
-               if (requiredSecret != null) {
-                   secret = true;
-                   if (!tmpMB.equals(requiredSecret)) {
-                       response.setStatus(403);
-                       adapter.log(request, response, 0);
-                       error = true;
-                   }
-               }
-               break;
-
-           default:
-               // Ignore unknown attribute for backward compatibility
-               break;
-
-           }
-
-       }
-
-       // Check if secret was submitted if required
-       if ((requiredSecret != null) && !secret) {
-           response.setStatus(403);
-           adapter.log(request, response, 0);
-           error = true;
-       }
-
-       // 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 = headers.setValue("host");
-               hostMB.setBytes(uriB, uriBCStart + pos + 3,
-                               slashPos - pos - 3);
-           }
-
-       }
-
-       MessageBytes valueMB = request.getMimeHeaders().getValue("host");
-       parseHost(valueMB);
-
-   }
-   
-   
-   /**
-    * Parse host.
-    */
-   protected void parseHost(MessageBytes valueMB) {
-
-       if (valueMB == null || valueMB.isNull()) {
-           // HTTP/1.0
-           request.setServerPort(request.getLocalPort());
-           try {
-               request.serverName().duplicate(request.localName());
-           } catch (IOException e) {
-               response.setStatus(400);
-               adapter.log(request, response, 0);
-               error = true;
-           }
-           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 (request.scheme().equalsIgnoreCase("https")) {
-               // 443 - Default HTTPS port
-               request.setServerPort(443);
-           } else {
-               // 80 - Default HTTTP port
-               request.setServerPort(80);
-           }
-           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.getDec(valueB[i + valueS]);
-               if (charValue == -1) {
-                   // Invalid character
-                   error = true;
-                   // 400 - Bad request
-                   response.setStatus(400);
-                   adapter.log(request, response, 0);
-                   break;
-               }
-               port = port + (charValue * mult);
-               mult = 10 * mult;
-           }
-           request.setServerPort(port);
-       }
-   }
-   
-   
-   /**
-    * When committing the response, we have to validate the set of headers, as
-    * well as setup the response filters.
-    */
-   protected void prepareResponse()
-       throws IOException {
-
-       response.setCommitted(true);
-
-       responseHeaderMessage.reset();
-       responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
-
-       // HTTP header contents
-       responseHeaderMessage.appendInt(response.getStatus());
-       String message = null;
-       if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
-               HttpMessages.isSafeInHttpHeader(response.getMessage())) {
-           message = response.getMessage();
-       }
-       if (message == null){
-           message = HttpMessages.getMessage(response.getStatus());
-       }
-       if (message == null) {
-           // mod_jk + httpd 2.x fails with a null status message - bug 45026
-           message = Integer.toString(response.getStatus());
-       }
-       tmpMB.setString(message);
-       responseHeaderMessage.appendBytes(tmpMB);
-
-       // Special headers
-       MimeHeaders headers = response.getMimeHeaders();
-       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);
-       }
-       long contentLength = response.getContentLengthLong();
-       if (contentLength >= 0) {
-           headers.setValue("Content-Length").setLong(contentLength);
-       }
-
-       // Other headers
-       int numHeaders = headers.size();
-       responseHeaderMessage.appendInt(numHeaders);
-       for (int i = 0; i < numHeaders; i++) {
-           MessageBytes hN = headers.getName(i);
-           int hC = Constants.getResponseAjpIndex(hN.toString());
-           if (hC > 0) {
-               responseHeaderMessage.appendInt(hC);
-           }
-           else {
-               responseHeaderMessage.appendBytes(hN);
-           }
-           MessageBytes hV=headers.getValue(i);
-           responseHeaderMessage.appendBytes(hV);
-       }
-
-       // Write to buffer
-       responseHeaderMessage.end();
-       output(responseHeaderMessage.getBuffer(), 0,
-               responseHeaderMessage.getLen());
-   }
-   
-   // Methods called by prepareResponse()
-   protected abstract void output(byte[] src, int offset, int length)
-           throws IOException;
-   
-   
-   // ------------------------------------- InputStreamInputBuffer Inner Class
-
-
-   /**
-    * This class is an input buffer which will read its data from an input
-    * stream.
-    */
-   protected class SocketInputBuffer
-       implements InputBuffer {
-
-
-       /**
-        * Read bytes into the specified chunk.
-        */
-       @Override
-       public int doRead(ByteChunk chunk, Request req )
-           throws IOException {
-
-           if (endOfStream) {
-               return -1;
-           }
-           if (first && req.getContentLengthLong() > 0) {
-               // Handle special first-body-chunk
-               if (!receive()) {
-                   return 0;
-               }
-           } else if (empty) {
-               if (!refillReadBuffer()) {
-                   return -1;
-               }
-           }
-           ByteChunk bc = bodyBytes.getByteChunk();
-           chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
-           empty = true;
-           return chunk.getLength();
-
-       }
-
-   }
-   
-   // Methods used by SocketInputBuffer
-   protected abstract boolean receive() throws IOException;
-   protected abstract boolean refillReadBuffer() throws IOException;
+    /**
+     * Send an action to the connector.
+     *
+     * @param actionCode Type of the action
+     * @param param Action parameter
+     */
+    @Override
+    public final void action(ActionCode actionCode, Object param) {
+
+        if (actionCode == ActionCode.COMMIT) {
+
+            if (response.isCommitted())
+                return;
+
+            // Validate and write response headers
+            try {
+                prepareResponse();
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+            try {
+                flush(false);
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+        } else if (actionCode == ActionCode.CLIENT_FLUSH) {
+
+            if (!response.isCommitted()) {
+                // Validate and write response headers
+                try {
+                    prepareResponse();
+                } catch (IOException e) {
+                    // Set error flag
+                    error = true;
+                    return;
+                }
+            }
+
+            try {
+                flush(true);
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+        } else if (actionCode == ActionCode.DISABLE_SWALLOW_INPUT) {
+            // TODO: Do not swallow request input but
+            // make sure we are closing the connection
+            error = true;
+
+        } else if (actionCode == ActionCode.CLOSE) {
+            // Close
+            // End the processing of the current request, and stop any further
+            // transactions with the client
+
+            try {
+                finish();
+            } catch (IOException e) {
+                // Set error flag
+                error = true;
+            }
+
+        } else if (actionCode == ActionCode.REQ_SSL_ATTRIBUTE ) {
+
+            if (!certificates.isNull()) {
+                ByteChunk certData = certificates.getByteChunk();
+                X509Certificate jsseCerts[] = null;
+                ByteArrayInputStream bais =
+                    new ByteArrayInputStream(certData.getBytes(),
+                            certData.getStart(),
+                            certData.getLength());
+                // Fill the  elements.
+                try {
+                    CertificateFactory cf;
+                    if (clientCertProvider == null) {
+                        cf = CertificateFactory.getInstance("X.509");
+                    } else {
+                        cf = CertificateFactory.getInstance("X.509",
+                                clientCertProvider);
+                    }
+                    while(bais.available() > 0) {
+                        X509Certificate cert = (X509Certificate)
+                        cf.generateCertificate(bais);
+                        if(jsseCerts == null) {
+                            jsseCerts = new X509Certificate[1];
+                            jsseCerts[0] = cert;
+                        } else {
+                            X509Certificate [] temp = new 
X509Certificate[jsseCerts.length+1];
+                            
System.arraycopy(jsseCerts,0,temp,0,jsseCerts.length);
+                            temp[jsseCerts.length] = cert;
+                            jsseCerts = temp;
+                        }
+                    }
+                } catch (java.security.cert.CertificateException e) {
+                    getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
+                    return;
+                } catch (NoSuchProviderException e) {
+                    getLog().error(sm.getString("ajpprocessor.certs.fail"), e);
+                    return;
+                }
+                request.setAttribute(SSLSupport.CERTIFICATE_KEY, jsseCerts);
+            }
+
+        } else if (actionCode == ActionCode.REQ_HOST_ATTRIBUTE) {
+
+            // Get remote host name using a DNS resolution
+            if (request.remoteHost().isNull()) {
+                try {
+                    request.remoteHost().setString(InetAddress.getByName
+                            (request.remoteAddr().toString()).getHostName());
+                } catch (IOException iex) {
+                    // Ignore
+                }
+            }
+
+        } else if (actionCode == ActionCode.REQ_LOCAL_ADDR_ATTRIBUTE) {
+
+            // Copy from local name for now, which should simply be an address
+            request.localAddr().setString(request.localName().toString());
+
+        } else if (actionCode == ActionCode.REQ_SET_BODY_REPLAY) {
+
+            // Set the given bytes as the content
+            ByteChunk bc = (ByteChunk) param;
+            int length = bc.getLength();
+            bodyBytes.setBytes(bc.getBytes(), bc.getStart(), length);
+            request.setContentLength(length);
+            first = false;
+            empty = false;
+            replay = true;
+
+        } else if (actionCode == ActionCode.ASYNC_START) {
+            asyncStateMachine.asyncStart((AsyncContextCallback) param);
+        } else if (actionCode == ActionCode.ASYNC_DISPATCHED) {
+            asyncStateMachine.asyncDispatched();
+        } else if (actionCode == ActionCode.ASYNC_TIMEOUT) {
+            AtomicBoolean result = (AtomicBoolean) param;
+            result.set(asyncStateMachine.asyncTimeout());
+        } else if (actionCode == ActionCode.ASYNC_RUN) {
+            asyncStateMachine.asyncRun((Runnable) param);
+        } else if (actionCode == ActionCode.ASYNC_ERROR) {
+            asyncStateMachine.asyncError();
+        } else if (actionCode == ActionCode.ASYNC_IS_STARTED) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsyncStarted());
+        } else if (actionCode == ActionCode.ASYNC_IS_DISPATCHING) {
+            ((AtomicBoolean) 
param).set(asyncStateMachine.isAsyncDispatching());
+        } else if (actionCode == ActionCode.ASYNC_IS_ASYNC) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsync());
+        } else if (actionCode == ActionCode.ASYNC_IS_TIMINGOUT) {
+            ((AtomicBoolean) param).set(asyncStateMachine.isAsyncTimingOut());
+        }  else {
+            actionInternal(actionCode, param);
+        }
+    }
+
+    // Methods called by action()
+    protected abstract void actionInternal(ActionCode actionCode, Object 
param);
+    protected abstract void flush(boolean tbd) throws IOException;
+    protected abstract void finish() throws IOException;
+
+
+    public SocketState asyncDispatch(SocketStatus status) {
+
+        RequestInfo rp = request.getRequestProcessor();
+        try {
+            rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
+            error = !adapter.asyncDispatch(request, response, status);
+        } catch (InterruptedIOException e) {
+            error = true;
+        } catch (Throwable t) {
+            ExceptionUtils.handleThrowable(t);
+            getLog().error(sm.getString("http11processor.request.process"), t);
+            error = true;
+        } finally {
+            if (error) {
+                // 500 - Internal Server Error
+                response.setStatus(500);
+                adapter.log(request, response, 0);
+            }
+        }
+
+        rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
+
+        if (isAsync()) {
+            if (error) {
+                request.updateCounters();
+                return SocketState.CLOSED;
+            } else {
+                return SocketState.LONG;
+            }
+        } else {
+            request.updateCounters();
+            if (error) {
+                return SocketState.CLOSED;
+            } else {
+                return SocketState.OPEN;
+            }
+        }
+    }
+
+
+    public void recycle() {
+        asyncStateMachine.recycle();
+
+        // Recycle Request object
+        first = true;
+        endOfStream = false;
+        empty = true;
+        replay = false;
+        finished = false;
+        request.recycle();
+        response.recycle();
+        certificates.recycle();
+        byteCount = 0;
+    }
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * After reading the request headers, we have to setup the request filters.
+     */
+    protected void prepareRequest() {
+
+        // Translate the HTTP method code to a String.
+        byte methodCode = requestHeaderMessage.getByte();
+        if (methodCode != Constants.SC_M_JK_STORED) {
+            String methodName = Constants.getMethodForCode(methodCode - 1);
+            request.method().setString(methodName);
+        }
+
+        requestHeaderMessage.getBytes(request.protocol());
+        requestHeaderMessage.getBytes(request.requestURI());
+
+        requestHeaderMessage.getBytes(request.remoteAddr());
+        requestHeaderMessage.getBytes(request.remoteHost());
+        requestHeaderMessage.getBytes(request.localName());
+        request.setLocalPort(requestHeaderMessage.getInt());
+
+        boolean isSSL = requestHeaderMessage.getByte() != 0;
+        if (isSSL) {
+            request.scheme().setString("https");
+        }
+
+        // Decode headers
+        MimeHeaders headers = request.getMimeHeaders();
+
+        int hCount = requestHeaderMessage.getInt();
+        for(int i = 0 ; i < hCount ; i++) {
+            String hName = null;
+
+            // Header names are encoded as either an integer code starting
+            // with 0xA0, or as a normal string (in which case the first
+            // two bytes are the length).
+            int isc = requestHeaderMessage.peekInt();
+            int hId = isc & 0xFF;
+
+            MessageBytes vMB = null;
+            isc &= 0xFF00;
+            if(0xA000 == isc) {
+                requestHeaderMessage.getInt(); // To advance the read position
+                hName = Constants.getHeaderForCode(hId - 1);
+                vMB = headers.addValue(hName);
+            } else {
+                // reset hId -- if the header currently being read
+                // happens to be 7 or 8 bytes long, the code below
+                // will think it's the content-type header or the
+                // content-length header - SC_REQ_CONTENT_TYPE=7,
+                // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
+                // behaviour.  see bug 5861 for more information.
+                hId = -1;
+                requestHeaderMessage.getBytes(tmpMB);
+                ByteChunk bc = tmpMB.getByteChunk();
+                vMB = headers.addValue(bc.getBuffer(),
+                        bc.getStart(), bc.getLength());
+            }
+
+            requestHeaderMessage.getBytes(vMB);
+
+            if (hId == Constants.SC_REQ_CONTENT_LENGTH ||
+                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
+                // just read the content-length header, so set it
+                long cl = vMB.getLong();
+                if(cl < Integer.MAX_VALUE)
+                    request.setContentLength( (int)cl );
+            } else if (hId == Constants.SC_REQ_CONTENT_TYPE ||
+                    (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
+                // just read the content-type header, so set it
+                ByteChunk bchunk = vMB.getByteChunk();
+                request.contentType().setBytes(bchunk.getBytes(),
+                        bchunk.getOffset(),
+                        bchunk.getLength());
+            }
+        }
+
+        // Decode extra attributes
+        boolean secret = false;
+        byte attributeCode;
+        while ((attributeCode = requestHeaderMessage.getByte())
+                != Constants.SC_A_ARE_DONE) {
+
+            switch (attributeCode) {
+
+            case Constants.SC_A_REQ_ATTRIBUTE :
+                requestHeaderMessage.getBytes(tmpMB);
+                String n = tmpMB.toString();
+                requestHeaderMessage.getBytes(tmpMB);
+                String v = tmpMB.toString();
+                /*
+                 * AJP13 misses to forward the remotePort.
+                 * Allow the AJP connector to add this info via
+                 * a private request attribute.
+                 * We will accept the forwarded data as the remote port,
+                 * and remove it from the public list of request attributes.
+                 */
+                if(n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
+                    try {
+                        request.setRemotePort(Integer.parseInt(v));
+                    } catch (NumberFormatException nfe) {
+                        // Ignore invalid value
+                    }
+                } else {
+                    request.setAttribute(n, v );
+                }
+                break;
+
+            case Constants.SC_A_CONTEXT :
+                requestHeaderMessage.getBytes(tmpMB);
+                // nothing
+                break;
+
+            case Constants.SC_A_SERVLET_PATH :
+                requestHeaderMessage.getBytes(tmpMB);
+                // nothing
+                break;
+
+            case Constants.SC_A_REMOTE_USER :
+                if (tomcatAuthentication) {
+                    // ignore server
+                    requestHeaderMessage.getBytes(tmpMB);
+                } else {
+                    requestHeaderMessage.getBytes(request.getRemoteUser());
+                }
+                break;
+
+            case Constants.SC_A_AUTH_TYPE :
+                if (tomcatAuthentication) {
+                    // ignore server
+                    requestHeaderMessage.getBytes(tmpMB);
+                } else {
+                    requestHeaderMessage.getBytes(request.getAuthType());
+                }
+                break;
+
+            case Constants.SC_A_QUERY_STRING :
+                requestHeaderMessage.getBytes(request.queryString());
+                break;
+
+            case Constants.SC_A_JVM_ROUTE :
+                requestHeaderMessage.getBytes(request.instanceId());
+                break;
+
+            case Constants.SC_A_SSL_CERT :
+                request.scheme().setString("https");
+                // SSL certificate extraction is lazy, moved to JkCoyoteHandler
+                requestHeaderMessage.getBytes(certificates);
+                break;
+
+            case Constants.SC_A_SSL_CIPHER :
+                request.scheme().setString("https");
+                requestHeaderMessage.getBytes(tmpMB);
+                request.setAttribute(SSLSupport.CIPHER_SUITE_KEY,
+                        tmpMB.toString());
+                break;
+
+            case Constants.SC_A_SSL_SESSION :
+                request.scheme().setString("https");
+                requestHeaderMessage.getBytes(tmpMB);
+                request.setAttribute(SSLSupport.SESSION_ID_KEY,
+                        tmpMB.toString());
+                break;
+
+            case Constants.SC_A_SSL_KEY_SIZE :
+                request.setAttribute(SSLSupport.KEY_SIZE_KEY,
+                        Integer.valueOf(requestHeaderMessage.getInt()));
+                break;
+
+            case Constants.SC_A_STORED_METHOD:
+                requestHeaderMessage.getBytes(request.method());
+                break;
+
+            case Constants.SC_A_SECRET:
+                requestHeaderMessage.getBytes(tmpMB);
+                if (requiredSecret != null) {
+                    secret = true;
+                    if (!tmpMB.equals(requiredSecret)) {
+                        response.setStatus(403);
+                        adapter.log(request, response, 0);
+                        error = true;
+                    }
+                }
+                break;
+
+            default:
+                // Ignore unknown attribute for backward compatibility
+                break;
+
+            }
+
+        }
+
+        // Check if secret was submitted if required
+        if ((requiredSecret != null) && !secret) {
+            response.setStatus(403);
+            adapter.log(request, response, 0);
+            error = true;
+        }
+
+        // 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 = headers.setValue("host");
+                hostMB.setBytes(uriB, uriBCStart + pos + 3,
+                        slashPos - pos - 3);
+            }
+
+        }
+
+        MessageBytes valueMB = request.getMimeHeaders().getValue("host");
+        parseHost(valueMB);
+
+    }
+
+
+    /**
+     * Parse host.
+     */
+    protected void parseHost(MessageBytes valueMB) {
+
+        if (valueMB == null || valueMB.isNull()) {
+            // HTTP/1.0
+            request.setServerPort(request.getLocalPort());
+            try {
+                request.serverName().duplicate(request.localName());
+            } catch (IOException e) {
+                response.setStatus(400);
+                adapter.log(request, response, 0);
+                error = true;
+            }
+            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 (request.scheme().equalsIgnoreCase("https")) {
+                // 443 - Default HTTPS port
+                request.setServerPort(443);
+            } else {
+                // 80 - Default HTTTP port
+                request.setServerPort(80);
+            }
+            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.getDec(valueB[i + valueS]);
+                if (charValue == -1) {
+                    // Invalid character
+                    error = true;
+                    // 400 - Bad request
+                    response.setStatus(400);
+                    adapter.log(request, response, 0);
+                    break;
+                }
+                port = port + (charValue * mult);
+                mult = 10 * mult;
+            }
+            request.setServerPort(port);
+        }
+    }
+
+
+    /**
+     * When committing the response, we have to validate the set of headers, as
+     * well as setup the response filters.
+     */
+    protected void prepareResponse()
+    throws IOException {
+
+        response.setCommitted(true);
+
+        responseHeaderMessage.reset();
+        responseHeaderMessage.appendByte(Constants.JK_AJP13_SEND_HEADERS);
+
+        // HTTP header contents
+        responseHeaderMessage.appendInt(response.getStatus());
+        String message = null;
+        if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
+                HttpMessages.isSafeInHttpHeader(response.getMessage())) {
+            message = response.getMessage();
+        }
+        if (message == null){
+            message = HttpMessages.getMessage(response.getStatus());
+        }
+        if (message == null) {
+            // mod_jk + httpd 2.x fails with a null status message - bug 45026
+            message = Integer.toString(response.getStatus());
+        }
+        tmpMB.setString(message);
+        responseHeaderMessage.appendBytes(tmpMB);
+
+        // Special headers
+        MimeHeaders headers = response.getMimeHeaders();
+        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);
+        }
+        long contentLength = response.getContentLengthLong();
+        if (contentLength >= 0) {
+            headers.setValue("Content-Length").setLong(contentLength);
+        }
+
+        // Other headers
+        int numHeaders = headers.size();
+        responseHeaderMessage.appendInt(numHeaders);
+        for (int i = 0; i < numHeaders; i++) {
+            MessageBytes hN = headers.getName(i);
+            int hC = Constants.getResponseAjpIndex(hN.toString());
+            if (hC > 0) {
+                responseHeaderMessage.appendInt(hC);
+            }
+            else {
+                responseHeaderMessage.appendBytes(hN);
+            }
+            MessageBytes hV=headers.getValue(i);
+            responseHeaderMessage.appendBytes(hV);
+        }
+
+        // Write to buffer
+        responseHeaderMessage.end();
+        output(responseHeaderMessage.getBuffer(), 0,
+                responseHeaderMessage.getLen());
+    }
+
+    // Methods called by prepareResponse()
+    protected abstract void output(byte[] src, int offset, int length)
+    throws IOException;
+
+
+    // ------------------------------------- InputStreamInputBuffer Inner Class
+
+
+    /**
+     * This class is an input buffer which will read its data from an input
+     * stream.
+     */
+    protected class SocketInputBuffer
+    implements InputBuffer {
+
+
+        /**
+         * Read bytes into the specified chunk.
+         */
+        @Override
+        public int doRead(ByteChunk chunk, Request req )
+        throws IOException {
+
+            if (endOfStream) {
+                return -1;
+            }
+            if (first && req.getContentLengthLong() > 0) {
+                // Handle special first-body-chunk
+                if (!receive()) {
+                    return 0;
+                }
+            } else if (empty) {
+                if (!refillReadBuffer()) {
+                    return -1;
+                }
+            }
+            ByteChunk bc = bodyBytes.getByteChunk();
+            chunk.setBytes(bc.getBuffer(), bc.getStart(), bc.getLength());
+            empty = true;
+            return chunk.getLength();
+
+        }
+
+    }
+
+    // Methods used by SocketInputBuffer
+    protected abstract boolean receive() throws IOException;
+    protected abstract boolean refillReadBuffer() throws IOException;
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to