* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
import java.io.ByteArrayInputStream;
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 extends AbstractProcessor {
+public abstract class AbstractAjpProcessor<S> extends AbstractProcessor {
protected abstract Log getLog();
protected abstract void finish() throws IOException;
+ public abstract SocketState process(SocketWrapper<S> socket)
+ throws IOException;
+
public SocketState asyncDispatch(SocketStatus status) {
RequestInfo rp = request.getRequestProcessor();
*/
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;
public abstract class AbstractAjpProtocol extends AbstractProtocol {
this.packetSize = packetSize;
}
}
+
+ protected abstract static class AbstractAjpConnectionHandler<S,P extends AbstractAjpProcessor<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);
+
+ 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) {
+ // In the middle of processing a request/response. Keep the
+ // socket associated with the processor.
+ 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.
+ 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 release(SocketWrapper<S> socket, P processor,
+ boolean socketClosing, boolean addToPoller);
+ }
}
* @author Costin Manolache
* @author Bill Barker
*/
-public class AjpAprProcessor extends AbstractAjpProcessor {
+public class AjpAprProcessor extends AbstractAjpProcessor<Long> {
/**
*
* @throws IOException error during an I/O operation
*/
+ @Override
public SocketState process(SocketWrapper<Long> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
* 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;
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;
}
return log;
}
- @Override
- public void recycle() {
- recycledProcessors.clear();
- }
-
/**
* Expected to be used by the handler once the processor is no longer
* required.
*/
+ @Override
public void release(SocketWrapper<Long> socket,
AjpAprProcessor processor, boolean isSocketClosing,
boolean addToPoller) {
@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.
- 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
- 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);
- }
- release(socket, processor, true, false);
- return SocketState.CLOSED;
- }
-
protected AjpAprProcessor createProcessor() {
AjpAprProcessor processor = new AjpAprProcessor(proto.packetSize, (AprEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);
/**
* Processes AJP requests using NIO.
*/
-public class AjpNioProcessor extends AbstractAjpProcessor {
+public class AjpNioProcessor extends AbstractAjpProcessor<NioChannel> {
/**
*
* @throws IOException error during an I/O operation
*/
+ @Override
public SocketState process(SocketWrapper<NioChannel> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
-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.NioChannel;
import org.apache.tomcat.util.net.NioEndpoint;
import org.apache.tomcat.util.net.NioEndpoint.Handler;
import org.apache.tomcat.util.net.SSLImplementation;
-import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapper;
protected static class AjpConnectionHandler
- extends AbstractConnectionHandler implements Handler {
+ extends AbstractAjpConnectionHandler<NioChannel, AjpNioProcessor>
+ implements Handler {
protected AjpNioProtocol proto;
- protected ConcurrentHashMap<SocketWrapper<NioChannel>, AjpNioProcessor> connections =
- new ConcurrentHashMap<SocketWrapper<NioChannel>, AjpNioProcessor>();
-
- protected RecycledProcessors<AjpNioProcessor> recycledProcessors =
- new RecycledProcessors<AjpNioProcessor>(this);
-
public AjpConnectionHandler(AjpNioProtocol proto) {
this.proto = proto;
}
}
@Override
- public void recycle() {
- recycledProcessors.clear();
- }
-
- @Override
public SSLImplementation getSslImplementation() {
// AJP does not support SSL
return null;
* Expected to be used by the handler once the processor is no longer
* required.
*/
+ @Override
public void release(SocketWrapper<NioChannel> socket,
AjpNioProcessor processor, boolean isSocketClosing,
boolean addToPoller) {
@Override
- public SocketState process(SocketWrapper<NioChannel> socket,
- SocketStatus status) {
- AjpNioProcessor processor = connections.remove(socket);
-
- socket.setAsync(false); //no longer check for timeout
-
- 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) {
- // In the middle of processing a request/response. Keep the
- // socket associated with the processor.
- 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.
- 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
- 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);
- }
- release(socket, processor, true, false);
- return SocketState.CLOSED;
- }
-
protected AjpNioProcessor createProcessor() {
AjpNioProcessor processor = new AjpNioProcessor(proto.packetSize, (NioEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);
* @author Costin Manolache
* @author Bill Barker
*/
-public class AjpProcessor extends AbstractAjpProcessor {
+public class AjpProcessor extends AbstractAjpProcessor<Socket> {
/**
*
* @throws IOException error during an I/O operation
*/
+ @Override
public SocketState process(SocketWrapper<Socket> socket)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.coyote.ajp;
import java.net.Socket;
-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.JIoEndpoint;
import org.apache.tomcat.util.net.JIoEndpoint.Handler;
import org.apache.tomcat.util.net.SSLImplementation;
-import org.apache.tomcat.util.net.SocketStatus;
import org.apache.tomcat.util.net.SocketWrapper;
protected static class AjpConnectionHandler
- extends AbstractConnectionHandler implements Handler {
+ extends AbstractAjpConnectionHandler<Socket,AjpProcessor>
+ implements Handler {
protected AjpProtocol proto;
- protected ConcurrentHashMap<SocketWrapper<Socket>, AjpProcessor> connections =
- new ConcurrentHashMap<SocketWrapper<Socket>, AjpProcessor>();
-
- protected RecycledProcessors<AjpProcessor> recycledProcessors =
- new RecycledProcessors<AjpProcessor>(this);
-
public AjpConnectionHandler(AjpProtocol proto) {
this.proto = proto;
}
return null;
}
- @Override
- public void recycle() {
- recycledProcessors.clear();
- }
-
/**
* Expected to be used by the handler once the processor is no longer
* required.
* @param isSocketClosing
* @param addToPoller Ignored for BIO
*/
+ @Override
public void release(SocketWrapper<Socket> socket,
AjpProcessor processor, boolean isSocketClosing,
boolean addToPoller) {
@Override
- public SocketState process(SocketWrapper<Socket> socket,
- SocketStatus status) {
- AjpProcessor 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) {
- // In the middle of processing a request/response. Keep the
- // socket associated with the processor.
- 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.
- 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
- 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);
- }
- release(socket, processor, true, false);
- return SocketState.CLOSED;
- }
-
protected AjpProcessor createProcessor() {
AjpProcessor processor = new AjpProcessor(proto.packetSize, (JIoEndpoint)proto.endpoint);
processor.setAdapter(proto.adapter);