*/
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;
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);
}
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;
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,
// ------------------------------------------- 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<SocketWrapper<S>,P> connections =
+ new ConcurrentHashMap<SocketWrapper<S>,P>();
+
+ protected RecycledProcessors<P,S> recycledProcessors =
+ new RecycledProcessors<P,S>(this);
+
+
protected abstract AbstractProtocol getProtocol();
- protected abstract Log getLog();
@Override
return global;
}
+ @Override
+ public void recycle() {
+ recycledProcessors.clear();
+ }
+
+
+ public SocketState process(SocketWrapper<S> socket,
+ SocketStatus status) {
+ P processor = connections.remove(socket);
+
+ 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 {
}
}
- protected void unregister(AbstractProcessor processor) {
+ protected void unregister(AbstractProcessor<S> processor) {
if (getProtocol().getDomain() != null) {
synchronized (this) {
try {
}
}
- 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;
}
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.net.SocketStatus;
-import org.apache.tomcat.util.net.SocketWrapper;
import org.apache.tomcat.util.res.StringManager;
/**
* Base class for AJP Processor implementations.
*/
-public abstract class AbstractAjpProcessor<S> extends AbstractProcessor {
+public abstract class AbstractAjpProcessor<S> extends AbstractProcessor<S> {
protected abstract Log getLog();
protected long byteCount = 0;
- /**
- * AJP does not support comet
- */
- protected final boolean comet = false;
-
// ------------------------------------------------------------ Constructor
public AbstractAjpProcessor(int packetSize, AbstractEndpoint endpoint) {
protected abstract void finish() throws IOException;
- public abstract SocketState process(SocketWrapper<S> socket)
- throws IOException;
-
+ @Override
public SocketState asyncDispatch(SocketStatus status) {
RequestInfo rp = request.getRequestProcessor();
}
- @SuppressWarnings("unused")
+ @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(
*/
package org.apache.coyote.ajp;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.coyote.AbstractProtocol;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapper;
import org.apache.tomcat.util.res.StringManager;
}
protected abstract static class AbstractAjpConnectionHandler<S,P extends AbstractAjpProcessor<S>>
- extends AbstractConnectionHandler {
-
- protected ConcurrentHashMap<SocketWrapper<S>,P> connections =
- new ConcurrentHashMap<SocketWrapper<S>,P>();
+ extends AbstractConnectionHandler<S, P> {
- protected RecycledProcessors<P> recycledProcessors =
- new RecycledProcessors<P>(this);
-
@Override
- public void recycle() {
- recycledProcessors.clear();
- }
-
- public SocketState process(SocketWrapper<S> socket,
- SocketStatus status) {
- P processor = connections.remove(socket);
-
- 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.comet) {
- 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();
- @SuppressWarnings("unused")
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, processor);
socket.setAsync(true);
-
}
- protected abstract void release(SocketWrapper<S> socket, P processor,
- boolean socketClosing, boolean addToPoller);
}
}
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;
import org.apache.tomcat.util.res.StringManager;
-public abstract class AbstractHttp11Processor<S> extends AbstractProcessor {
+public abstract class AbstractHttp11Processor<S> extends AbstractProcessor<S> {
protected abstract Log getLog();
}
- public abstract SocketState process(SocketWrapper<S> socket)
- throws IOException;
-
+ @Override
public SocketState asyncDispatch(SocketStatus status) {
RequestInfo rp = request.getRequestProcessor();
}
- public abstract SocketState event(SocketStatus status) throws IOException;
+ @Override
+ public boolean isComet() {
+ return comet;
+ }
/**
*/
package org.apache.coyote.http11;
-import java.util.concurrent.ConcurrentHashMap;
import org.apache.coyote.AbstractProtocol;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.net.SocketStatus;
-import org.apache.tomcat.util.net.SocketWrapper;
import org.apache.tomcat.util.res.StringManager;
public abstract class AbstractHttp11Protocol extends AbstractProtocol {
public void setMaxKeepAliveRequests(int mkar) {
endpoint.setMaxKeepAliveRequests(mkar);
}
-
-
- protected abstract static class AbstractHttp11ConnectionHandler<S,P extends AbstractHttp11Processor<S>>
- extends AbstractConnectionHandler {
-
- protected ConcurrentHashMap<SocketWrapper<S>,P> connections =
- new ConcurrentHashMap<SocketWrapper<S>,P>();
-
- protected RecycledProcessors<P> recycledProcessors =
- new RecycledProcessors<P>(this);
-
- @Override
- public void recycle() {
- recycledProcessors.clear();
- }
-
- public SocketState process(SocketWrapper<S> socket,
- SocketStatus status) {
- P processor = connections.remove(socket);
-
- socket.setAsync(false); //no longer check for timeout
-
- 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.comet) {
- 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(
- "http11protocol.proto.socketexception.debug"), e);
- } catch (java.io.IOException e) {
- // IOExceptions are normal
- getLog().debug(sm.getString(
- "http11protocol.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("http11protocol.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);
- }
}
// -------------------- Connection handler --------------------
protected static class Http11ConnectionHandler
- extends AbstractHttp11ConnectionHandler<Long,Http11AprProcessor> implements Handler {
+ extends AbstractConnectionHandler<Long,Http11AprProcessor> implements Handler {
protected Http11AprProtocol proto;
// -------------------- Connection handler --------------------
protected static class Http11ConnectionHandler
- extends AbstractHttp11ConnectionHandler<NioChannel,Http11NioProcessor>
+ extends AbstractConnectionHandler<NioChannel,Http11NioProcessor>
implements Handler {
protected Http11NioProtocol proto;
// ----------------------------------- Http11ConnectionHandler Inner Class
protected static class Http11ConnectionHandler
- extends AbstractHttp11ConnectionHandler<Socket, Http11Processor> implements Handler {
+ extends AbstractConnectionHandler<Socket, Http11Processor> implements Handler {
protected Http11Protocol proto;