You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by xu...@apache.org on 2011/07/11 08:29:23 UTC
svn commit: r1145039 [1/2] - in
/geronimo/external/trunk/tomcat-parent-7.0.18: ./
catalina/src/main/java/org/apache/catalina/connector/
catalina/src/main/java/org/apache/catalina/security/
catalina/src/main/java/org/apache/catalina/startup/ catalina/sr...
Author: xuhaihong
Date: Mon Jul 11 06:29:23 2011
New Revision: 1145039
URL: http://svn.apache.org/viewvc?rev=1145039&view=rev
Log:
Merge the changes from Tomcat trunk to rev.1144976
Added:
geronimo/external/trunk/tomcat-parent-7.0.18/util/src/main/java/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd (with props)
Removed:
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/ClusterRuleSetFactory.java
Modified:
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/AbstractHttp11Processor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11AprProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11AprProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11NioProcessor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11NioProtocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11Processor.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/http11/Http11Protocol.java
geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/tomcat/util/net/AbstractEndpoint.java
geronimo/external/trunk/tomcat-parent-7.0.18/pom.xml
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/connector/CoyoteAdapter.java Mon Jul 11 06:29:23 2011
@@ -269,6 +269,7 @@ public class CoyoteAdapter implements Ad
boolean comet = false;
boolean success = true;
AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
+ req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
try {
if (!request.isAsync() && !comet) {
// Error or timeout - need to tell listeners the request is over
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/security/SecurityClassLoad.java Mon Jul 11 06:29:23 2011
@@ -239,6 +239,7 @@ public final class SecurityClassLoad {
private static final void loadTomcatPackage(ClassLoader loader)
throws Exception {
final String basePackage = "org.apache.tomcat.";
+ loader.loadClass(basePackage + "util.buf.HexUtils");
loader.loadClass(basePackage + "util.buf.StringCache");
loader.loadClass(basePackage + "util.buf.StringCache$ByteEntry");
loader.loadClass(basePackage + "util.buf.StringCache$CharEntry");
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/startup/Catalina.java Mon Jul 11 06:29:23 2011
@@ -36,6 +36,7 @@ import org.apache.catalina.LifecycleExce
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Server;
import org.apache.catalina.core.StandardServer;
+import org.apache.catalina.ha.ClusterRuleSet;
import org.apache.catalina.security.SecurityConfig;
import org.apache.juli.ClassLoaderLogManager;
import org.apache.tomcat.util.ExceptionUtils;
@@ -373,13 +374,13 @@ public class Catalina {
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
- digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
+ digester.addRuleSet(new ClusterRuleSet("Server/Service/Engine/Host/Cluster/"));
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
// When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine",
new SetParentClassLoaderRule(parentClassLoader));
- digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/"));
+ digester.addRuleSet(new ClusterRuleSet("Server/Service/Engine/Cluster/"));
long t2=System.currentTimeMillis();
if (log.isDebugEnabled())
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/catalina/valves/AccessLogValve.java Mon Jul 11 06:29:23 2011
@@ -263,7 +263,7 @@ public class AccessLogValve extends Valv
private class Cache {
/* CLF log format */
- private static final String cLFFormat = "dd/MMM/yyy:HH:mm:ss";
+ private static final String cLFFormat = "dd/MMM/yyyy:HH:mm:ss";
/* Second used to retrieve CLF format in most recent invocation */
private long previousSeconds = 0L;
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProcessor.java Mon Jul 11 06:29:23 2011
@@ -16,16 +16,19 @@
*/
package org.apache.coyote;
+import java.io.IOException;
import java.util.concurrent.Executor;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
+import org.apache.tomcat.util.net.SocketStatus;
+import org.apache.tomcat.util.net.SocketWrapper;
/**
* Provides functionality and attributes common to all supported protocols
* (currently HTTP and AJP).
*/
-public abstract class AbstractProcessor implements ActionHook, Processor {
+public abstract class AbstractProcessor<S> implements ActionHook, Processor {
protected Adapter adapter;
protected final AsyncStateMachine asyncStateMachine;
@@ -100,4 +103,25 @@ public abstract class AbstractProcessor
public SocketState asyncPostProcess() {
return asyncStateMachine.asyncPostProcess();
}
+
+ protected abstract boolean isComet();
+
+ /**
+ * Process HTTP requests. All requests are treated as HTTP requests to start
+ * with although they may change type during processing.
+ */
+ public abstract SocketState process(SocketWrapper<S> socket)
+ throws IOException;
+
+
+ /**
+ * Process in-progress Comet requests. These will start as HTTP requests.
+ */
+ public abstract SocketState event(SocketStatus status) throws IOException;
+
+ /**
+ * Process in-progress Servlet 3.0 Async requests. These will start as HTTP
+ * requests.
+ */
+ public abstract SocketState asyncDispatch(SocketStatus status);
}
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/AbstractProtocol.java Mon Jul 11 06:29:23 2011
@@ -17,6 +17,7 @@
package org.apache.coyote;
import java.net.InetAddress;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -28,9 +29,12 @@ import javax.management.MalformedObjectN
import javax.management.ObjectName;
import org.apache.juli.logging.Log;
+import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler;
+import org.apache.tomcat.util.net.SocketStatus;
+import org.apache.tomcat.util.net.SocketWrapper;
import org.apache.tomcat.util.res.StringManager;
public abstract class AbstractProtocol implements ProtocolHandler,
@@ -229,8 +233,7 @@ public abstract class AbstractProtocol i
name.append('-');
}
name.append(endpoint.getPort());
- String quotedName = ObjectName.quote(name.toString());
- return quotedName.substring(1, quotedName.length()-1);
+ return ObjectName.quote(name.toString());
}
@@ -359,7 +362,8 @@ public abstract class AbstractProtocol i
getHandler().getGlobal(), rgOname, null );
}
- endpoint.setName(getName());
+ String endpointName = getName();
+ endpoint.setName(endpointName.substring(1, endpointName.length()-1));
try {
endpoint.init();
@@ -456,14 +460,22 @@ public abstract class AbstractProtocol i
// ------------------------------------------- Connection handler base class
- protected abstract static class AbstractConnectionHandler
+ protected abstract static class AbstractConnectionHandler<S,P extends AbstractProcessor<S>>
implements AbstractEndpoint.Handler {
+ protected abstract Log getLog();
+
protected RequestGroupInfo global = new RequestGroupInfo();
protected AtomicLong registerCount = new AtomicLong(0);
+ protected ConcurrentHashMap<S,P> connections =
+ new ConcurrentHashMap<S,P>();
+
+ protected RecycledProcessors<P,S> recycledProcessors =
+ new RecycledProcessors<P,S>(this);
+
+
protected abstract AbstractProtocol getProtocol();
- protected abstract Log getLog();
@Override
@@ -471,8 +483,88 @@ public abstract class AbstractProtocol i
return global;
}
+ @Override
+ public void recycle() {
+ recycledProcessors.clear();
+ }
+
+
+ public SocketState process(SocketWrapper<S> socket,
+ SocketStatus status) {
+ P processor = connections.remove(socket.getSocket());
+
+ socket.setAsync(false);
+
+ try {
+ if (processor == null) {
+ processor = recycledProcessors.poll();
+ }
+ if (processor == null) {
+ processor = createProcessor();
+ }
+
+ initSsl(socket, processor);
+
+ SocketState state = SocketState.CLOSED;
+ do {
+ if (processor.isAsync() || state == SocketState.ASYNC_END) {
+ state = processor.asyncDispatch(status);
+ } else if (processor.isComet()) {
+ state = processor.event(status);
+ } else {
+ state = processor.process(socket);
+ }
+
+ if (state != SocketState.CLOSED && processor.isAsync()) {
+ state = processor.asyncPostProcess();
+ }
+ } while (state == SocketState.ASYNC_END);
+
+ if (state == SocketState.LONG) {
+ // In the middle of processing a request/response. Keep the
+ // socket associated with the processor. Exact requirements
+ // depend on type of long poll
+ longPoll(socket, processor);
+ } else if (state == SocketState.OPEN){
+ // In keep-alive but between requests. OK to recycle
+ // processor. Continue to poll for the next request.
+ release(socket, processor, false, true);
+ } else {
+ // Connection closed. OK to recycle the processor.
+ release(socket, processor, true, false);
+ }
+ return state;
+ } catch(java.net.SocketException e) {
+ // SocketExceptions are normal
+ getLog().debug(sm.getString(
+ "ajpprotocol.proto.socketexception.debug"), e);
+ } catch (java.io.IOException e) {
+ // IOExceptions are normal
+ getLog().debug(sm.getString(
+ "ajpprotocol.proto.ioexception.debug"), e);
+ }
+ // Future developers: if you discover any other
+ // rare-but-nonfatal exceptions, catch them here, and log as
+ // above.
+ catch (Throwable e) {
+ ExceptionUtils.handleThrowable(e);
+ // any other exception or error is odd. Here we log it
+ // with "ERROR" level, so it will show up even on
+ // less-than-verbose logs.
+ getLog().error(sm.getString("ajpprotocol.proto.error"), e);
+ }
+ release(socket, processor, true, false);
+ return SocketState.CLOSED;
+ }
+
+ protected abstract P createProcessor();
+ protected abstract void initSsl(SocketWrapper<S> socket, P processor);
+ protected abstract void longPoll(SocketWrapper<S> socket, P processor);
+ protected abstract void release(SocketWrapper<S> socket, P processor,
+ boolean socketClosing, boolean addToPoller);
+
- protected void register(AbstractProcessor processor) {
+ protected void register(AbstractProcessor<S> processor) {
if (getProtocol().getDomain() != null) {
synchronized (this) {
try {
@@ -499,7 +591,7 @@ public abstract class AbstractProtocol i
}
}
- protected void unregister(AbstractProcessor processor) {
+ protected void unregister(AbstractProcessor<S> processor) {
if (getProtocol().getDomain() != null) {
synchronized (this) {
try {
@@ -521,14 +613,14 @@ public abstract class AbstractProtocol i
}
}
- protected static class RecycledProcessors<P extends AbstractProcessor>
+ protected static class RecycledProcessors<P extends AbstractProcessor<S>, S>
extends ConcurrentLinkedQueue<P> {
private static final long serialVersionUID = 1L;
- private AbstractConnectionHandler handler;
+ private transient AbstractConnectionHandler<S,P> handler;
protected AtomicInteger size = new AtomicInteger(0);
- public RecycledProcessors(AbstractConnectionHandler handler) {
+ public RecycledProcessors(AbstractConnectionHandler<S,P> handler) {
this.handler = handler;
}
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Mon Jul 11 06:29:23 2011
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
import java.io.ByteArrayInputStream;
@@ -48,7 +47,7 @@ import org.apache.tomcat.util.res.String
/**
* Base class for AJP Processor implementations.
*/
-public abstract class AbstractAjpProcessor extends AbstractProcessor {
+public abstract class AbstractAjpProcessor<S> extends AbstractProcessor<S> {
protected abstract Log getLog();
@@ -70,7 +69,7 @@ public abstract class AbstractAjpProcess
* Flush message array.
*/
protected static final byte[] flushMessageArray;
-
+
/**
* Pong message array.
@@ -88,7 +87,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 +98,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 +109,7 @@ public abstract class AbstractAjpProcess
0, pongMessage.getLen());
}
-
+
// ----------------------------------------------------- Instance Variables
@@ -146,7 +145,7 @@ public abstract class AbstractAjpProcess
*/
protected AjpMessage bodyMessage = null;
-
+
/**
* Body message.
*/
@@ -205,28 +204,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 +236,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,651 +288,670 @@ 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 (error) {
- response.setStatus(500);
- }
- 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;
+
+
+ @Override
+ 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;
+ }
+ }
+ }
+
+
+ @Override
+ protected final boolean isComet() {
+ // AJP does not support Comet
+ return false;
+ }
+
+ @Override
+ public SocketState event(SocketStatus status) throws IOException {
+ // Should never reach this code but in case we do...
+ throw new IOException(
+ sm.getString("ajpprocessor.comet.notsupported"));
+ }
+
+ /**
+ * Recycle the processor, ready for the next request which may be on the
+ * same connection or a different connection.
+ *
+ * @param socketClosing Indicates if the socket is about to be closed
+ * allowing the processor to perform any additional
+ * clean-up that may be required
+ */
+ public void recycle(boolean socketClosing) {
+ 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;
}
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Mon Jul 11 06:29:23 2011
@@ -17,6 +17,7 @@
package org.apache.coyote.ajp;
import org.apache.coyote.AbstractProtocol;
+import org.apache.tomcat.util.net.SocketWrapper;
import org.apache.tomcat.util.res.StringManager;
public abstract class AbstractAjpProtocol extends AbstractProtocol {
@@ -70,4 +71,20 @@ public abstract class AbstractAjpProtoco
this.packetSize = packetSize;
}
}
+
+ protected abstract static class AbstractAjpConnectionHandler<S,P extends AbstractAjpProcessor<S>>
+ extends AbstractConnectionHandler<S, P> {
+
+ @Override
+ protected void initSsl(SocketWrapper<S> socket, P processor) {
+ // NOOP for AJP
+ }
+
+ @Override
+ protected void longPoll(SocketWrapper<S> socket, P processor) {
+ // Same requirements for all AJP connectors
+ connections.put(socket.getSocket(), processor);
+ socket.setAsync(true);
+ }
+ }
}
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProcessor.java Mon Jul 11 06:29:23 2011
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
import java.io.IOException;
@@ -31,8 +30,6 @@ import org.apache.tomcat.jni.Socket;
import org.apache.tomcat.jni.Status;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.AprEndpoint;
import org.apache.tomcat.util.net.SocketStatus;
@@ -50,7 +47,7 @@ import org.apache.tomcat.util.net.Socket
* @author Costin Manolache
* @author Bill Barker
*/
-public class AjpAprProcessor extends AbstractAjpProcessor {
+public class AjpAprProcessor extends AbstractAjpProcessor<Long> {
/**
@@ -76,13 +73,6 @@ public class AjpAprProcessor extends Abs
inputBuffer = ByteBuffer.allocateDirect(packetSize * 2);
inputBuffer.limit(0);
outputBuffer = ByteBuffer.allocateDirect(packetSize * 2);
-
- // Cause loading of HexUtils
- HexUtils.load();
-
- // Cause loading of HttpMessages
- HttpMessages.getMessage(200);
-
}
@@ -116,6 +106,7 @@ public class AjpAprProcessor extends Abs
*
* @throws IOException error during an I/O operation
*/
+ @Override
public SocketState process(SocketWrapper<Long> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
@@ -229,7 +220,7 @@ public class AjpAprProcessor extends Abs
request.updateCounters();
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
- recycle();
+ recycle(false);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
@@ -497,8 +488,8 @@ public class AjpAprProcessor extends Abs
* Recycle the processor.
*/
@Override
- public void recycle() {
- super.recycle();
+ public void recycle(boolean socketClosing) {
+ super.recycle(socketClosing);
inputBuffer.clear();
inputBuffer.limit(0);
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpAprProtocol.java Mon Jul 11 06:29:23 2011
@@ -14,19 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.coyote.AbstractProtocol;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AprEndpoint;
import org.apache.tomcat.util.net.AprEndpoint.Handler;
-import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapper;
@@ -100,16 +95,11 @@ public class AjpAprProtocol extends Abst
protected static class AjpConnectionHandler
- extends AbstractConnectionHandler implements Handler {
+ extends AbstractAjpConnectionHandler<Long,AjpAprProcessor>
+ implements Handler {
protected AjpAprProtocol proto;
- protected ConcurrentHashMap<SocketWrapper<Long>, AjpAprProcessor> connections =
- new ConcurrentHashMap<SocketWrapper<Long>, AjpAprProcessor>();
-
- protected RecycledProcessors<AjpAprProcessor> recycledProcessors =
- new RecycledProcessors<AjpAprProcessor>(this);
-
public AjpConnectionHandler(AjpAprProtocol proto) {
this.proto = proto;
}
@@ -124,81 +114,24 @@ public class AjpAprProtocol extends Abst
return log;
}
+ /**
+ * Expected to be used by the handler once the processor is no longer
+ * required.
+ */
@Override
- public void recycle() {
- recycledProcessors.clear();
- }
-
- @Override
- public SocketState process(SocketWrapper<Long> socket,
- SocketStatus status) {
- AjpAprProcessor processor = connections.remove(socket);
-
- socket.setAsync(false);
-
- try {
- if (processor == null) {
- processor = recycledProcessors.poll();
- }
- if (processor == null) {
- processor = createProcessor();
- }
-
- SocketState state = SocketState.CLOSED;
- do {
- if (processor.isAsync() || state == SocketState.ASYNC_END) {
- state = processor.asyncDispatch(status);
- } else {
- state = processor.process(socket);
- }
-
- if (state != SocketState.CLOSED && processor.isAsync()) {
- state = processor.asyncPostProcess();
- }
- } while (state == SocketState.ASYNC_END);
-
- if (state == SocketState.LONG) {
- // Need to make socket available for next processing cycle
- // but no need for the poller
- connections.put(socket, processor);
- socket.setAsync(true);
- } else if (state == SocketState.OPEN){
- // In keep-alive but between requests. OK to recycle
- // processor. Continue to poll for the next request.
- processor.recycle();
- recycledProcessors.offer(processor);
- ((AprEndpoint)proto.endpoint).getPoller().add(
- socket.getSocket().longValue());
- } else {
- processor.recycle();
- recycledProcessors.offer(processor);
- }
- return state;
-
- } catch(java.net.SocketException e) {
- // SocketExceptions are normal
- log.debug(sm.getString(
- "ajpprotocol.proto.socketexception.debug"), e);
- } catch (java.io.IOException e) {
- // IOExceptions are normal
- log.debug(sm.getString(
- "ajpprotocol.proto.ioexception.debug"), e);
- }
- // Future developers: if you discover any other
- // rare-but-nonfatal exceptions, catch them here, and log as
- // above.
- catch (Throwable e) {
- ExceptionUtils.handleThrowable(e);
- // any other exception or error is odd. Here we log it
- // with "ERROR" level, so it will show up even on
- // less-than-verbose logs.
- log.error(sm.getString("ajpprotocol.proto.error"), e);
- }
- processor.recycle();
+ public void release(SocketWrapper<Long> socket,
+ AjpAprProcessor processor, boolean isSocketClosing,
+ boolean addToPoller) {
+ processor.recycle(isSocketClosing);
recycledProcessors.offer(processor);
- return SocketState.CLOSED;
+ if (addToPoller) {
+ ((AprEndpoint)proto.endpoint).getPoller().add(
+ socket.getSocket().longValue());
+ }
}
+
+ @Override
protected AjpAprProcessor createProcessor() {
AjpAprProcessor processor = new AjpAprProcessor(proto.packetSize, (AprEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);
Modified: geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java?rev=1145039&r1=1145038&r2=1145039&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.18/catalina/src/main/java/org/apache/coyote/ajp/AjpNioProcessor.java Mon Jul 11 06:29:23 2011
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
import java.io.EOFException;
@@ -31,8 +30,6 @@ import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.NioChannel;
import org.apache.tomcat.util.net.NioEndpoint;
@@ -45,7 +42,7 @@ import org.apache.tomcat.util.net.Socket
/**
* Processes AJP requests using NIO.
*/
-public class AjpNioProcessor extends AbstractAjpProcessor {
+public class AjpNioProcessor extends AbstractAjpProcessor<NioChannel> {
/**
@@ -67,13 +64,6 @@ public class AjpNioProcessor extends Abs
response.setOutputBuffer(new SocketOutputBuffer());
pool = endpoint.getSelectorPool();
-
- // Cause loading of HexUtils
- HexUtils.load();
-
- // Cause loading of HttpMessages
- HttpMessages.getMessage(200);
-
}
@@ -101,6 +91,7 @@ public class AjpNioProcessor extends Abs
*
* @throws IOException error during an I/O operation
*/
+ @Override
public SocketState process(SocketWrapper<NioChannel> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
@@ -137,14 +128,14 @@ public class AjpNioProcessor extends Abs
} catch (IOException e) {
error = true;
}
- recycle();
+ recycle(true);
continue;
} else if(type != Constants.JK_AJP13_FORWARD_REQUEST) {
// Usually the servlet didn't read the previous request body
if(log.isDebugEnabled()) {
log.debug("Unexpected message: "+type);
}
- recycle();
+ recycle(false);
continue;
}
request.setStartTime(System.currentTimeMillis());
@@ -226,7 +217,7 @@ public class AjpNioProcessor extends Abs
socket.setTimeout(keepAliveTimeout);
}
- recycle();
+ recycle(true);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);