blob: 2e5ca1315939b091c9b363a365814aa56c482d4f [file] [log] [blame]
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.axis2.transport.http.server;
import java.io.IOException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Iterator;
import javax.xml.namespace.QName;
import org.apache.axis2.Constants;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.SessionContext;
import org.apache.axis2.description.TransportInDescription;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisEngine;
import org.apache.axis2.util.UUIDGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.UnsupportedHttpVersionException;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
public class DefaultHttpServiceProcessor extends HttpServiceProcessor {
private static final Log LOG = LogFactory.getLog(DefaultHttpServiceProcessor.class);
private static final Log HEADERLOG = LogFactory.getLog("org.apache.axis2.transport.http.server.wire");
private final ConfigurationContext configurationContext;
private final SessionManager sessionManager;
private final Worker worker;
private final IOProcessorCallback callback;
private HttpServerConnection conn;
private HttpContext httpcontext = null;
public DefaultHttpServiceProcessor(
final HttpServerConnection conn,
final ConfigurationContext configurationContext,
final SessionManager sessionManager,
final Worker worker,
final IOProcessorCallback callback) {
super(conn);
this.conn = conn;
if (worker == null) {
throw new IllegalArgumentException("Worker may not be null");
}
if (configurationContext == null) {
throw new IllegalArgumentException("Configuration context may not be null");
}
if (sessionManager == null) {
throw new IllegalArgumentException("Session manager may not be null");
}
this.configurationContext = configurationContext;
this.sessionManager = sessionManager;
this.worker = worker;
this.callback = callback;
// Add required protocol interceptors
addInterceptor(new RequestSessionCookie());
addInterceptor(new ResponseDate());
addInterceptor(new ResponseServer());
addInterceptor(new ResponseContent());
addInterceptor(new ResponseConnControl());
addInterceptor(new ResponseSessionCookie());
}
protected void postprocessResponse(final HttpResponse response, final HttpContext context)
throws IOException, HttpException {
super.postprocessResponse(response, context);
if (HEADERLOG.isDebugEnabled()) {
HEADERLOG.debug("<< " + response.getStatusLine().toString());
Header[] headers = response.getAllHeaders();
for (int i = 0; i < headers.length; i++) {
HEADERLOG.debug("<< " + headers[i].toString());
}
}
}
protected void preprocessRequest(final HttpRequest request, final HttpContext context)
throws IOException, HttpException {
// As of next version of HttpCore the HTTP execution context can be retrieved
// by calling #getContext()
this.httpcontext = context;
super.preprocessRequest(request, context);
if (HEADERLOG.isDebugEnabled()) {
HEADERLOG.debug(">> " + request.getRequestLine().toString());
Header[] headers = request.getAllHeaders();
for (int i = 0; i < headers.length; i++) {
HEADERLOG.debug(">> " + headers[i].toString());
}
}
}
protected void doService(final HttpRequest request, final HttpResponse response)
throws HttpException, IOException {
RequestLine reqline = request.getRequestLine();
if (LOG.isDebugEnabled()) {
LOG.debug("Request method: " + reqline.getMethod());
LOG.debug("Target URI: " + reqline.getUri());
}
HttpVersion ver = reqline.getHttpVersion();
if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
throw new UnsupportedHttpVersionException("Unsupported HTTP version: " + ver);
}
MessageContext msgContext = new MessageContext();
msgContext.setIncomingTransportName(Constants.TRANSPORT_HTTP);
if (conn instanceof DefaultHttpConnectionFactory.Axis2HttpServerConnection) {
DefaultHttpConnectionFactory.Axis2HttpServerConnection axis2Con =
(DefaultHttpConnectionFactory.Axis2HttpServerConnection) conn;
msgContext.setProperty(MessageContext.REMOTE_ADDR, axis2Con.getRemoteIPAddress());
LOG.debug("Remote address of the connection : " + axis2Con.getRemoteIPAddress());
}
try {
TransportOutDescription transportOut = this.configurationContext.getAxisConfiguration()
.getTransportOut(new QName(Constants.TRANSPORT_HTTP));
TransportInDescription transportIn = this.configurationContext.getAxisConfiguration()
.getTransportIn(new QName(Constants.TRANSPORT_HTTP));
msgContext.setConfigurationContext(this.configurationContext);
String sessionKey = (String) this.httpcontext.getAttribute(HTTPConstants.COOKIE_STRING);
if (this.configurationContext.getAxisConfiguration().isManageTransportSession()) {
SessionContext sessionContext = this.sessionManager.getSessionContext(sessionKey);
msgContext.setSessionContext(sessionContext);
}
msgContext.setTransportIn(transportIn);
msgContext.setTransportOut(transportOut);
msgContext.setServiceGroupContextId(UUIDGenerator.getUUID());
msgContext.setServerSide(true);
msgContext.setProperty(Constants.Configuration.TRANSPORT_IN_URL, reqline.getUri());
// set the transport Headers
HashMap headerMap = new HashMap();
for (Iterator it = request.headerIterator(); it.hasNext();) {
Header header = (Header) it.next();
headerMap.put(header.getName(), header.getValue());
}
msgContext.setProperty(MessageContext.TRANSPORT_HEADERS, headerMap);
this.httpcontext.setAttribute(AxisParams.MESSAGE_CONTEXT, msgContext);
this.worker.service(request, response, msgContext);
} catch (SocketException ex) {
// Socket is unreliable.
throw ex;
} catch (HttpException ex) {
// HTTP protocol violation. Transport is unrelaible
throw ex;
} catch (Throwable e) {
try {
AxisEngine engine = new AxisEngine(this.configurationContext);
OutputBuffer outbuffer = new OutputBuffer();
msgContext.setProperty(MessageContext.TRANSPORT_OUT, outbuffer.getOutputStream());
msgContext.setProperty(Constants.OUT_TRANSPORT_INFO, outbuffer);
MessageContext faultContext = engine.createFaultMessageContext(msgContext, e);
// If the fault is not going along the back channel we should be 202ing
if (AddressingHelper.isFaultRedirected(msgContext)) {
response.setStatusLine(new StatusLine(ver, 202, "Accepted"));
} else {
response.setStatusLine(new StatusLine(ver, 500, "Internal server error"));
}
engine.sendFault(faultContext);
response.setEntity(outbuffer);
} catch (Exception ex) {
if (AddressingHelper.isFaultRedirected(msgContext)) {
response.setStatusLine(new StatusLine(ver, 202, "Accepted"));
} else {
response.setStatusLine(new StatusLine(ver, 500, "Internal server error"));
String msg = ex.getMessage();
StringEntity entity;
if (msg != null && msg.trim().length() != 0) {
entity = new StringEntity(msg);
} else {
entity = new StringEntity("Exception message unknown");
}
entity.setContentType("text/plain");
response.setEntity(entity);
}
}
}
}
protected void logIOException(final IOException ex) {
if (ex instanceof SocketTimeoutException) {
LOG.debug(ex.getMessage());
} else if (ex instanceof SocketException) {
LOG.debug(ex.getMessage());
} else {
LOG.warn(ex.getMessage(), ex);
}
}
protected void logMessage(final String s) {
LOG.debug(s);
}
protected void logProtocolException(final HttpException ex) {
if (LOG.isWarnEnabled()) {
LOG.warn("HTTP protocol error: " + ex.getMessage());
}
}
public void close() throws IOException {
closeConnection();
}
public void run() {
LOG.debug("New connection thread");
try {
while (!Thread.interrupted() && !isDestroyed() && isActive()) {
handleRequest();
}
} finally {
destroy();
if (this.callback != null) {
this.callback.completed(this);
}
}
}
}