blob: 9ead24126e526807be2b855a9bdb48088357183d [file] [log] [blame]
/*
* Copyright 2004,2005 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.
*/
package org.apache.axis2.transport.http;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.impl.MIMEOutputUtils;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.transport.OutTransportInfo;
import org.apache.axis2.transport.TransportSender;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
public class CommonsHTTPTransportSender extends AbstractHandler implements TransportSender {
protected static final String PROXY_HOST_NAME = "proxy_host";
protected static final String PROXY_PORT = "proxy_port";
int soTimeout = HTTPConstants.DEFAULT_SO_TIMEOUT;
/**
* proxydiscription
*/
protected TransportOutDescription proxyOutSetting = null;
private static final Log log = LogFactory.getLog(CommonsHTTPTransportSender.class);
protected String httpVersion = HTTPConstants.HEADER_PROTOCOL_11;
private boolean chunked = false;
int connectionTimeout = HTTPConstants.DEFAULT_CONNECTION_TIMEOUT;
public CommonsHTTPTransportSender() {
}
public void cleanup(MessageContext msgContext) throws AxisFault {
HttpMethod httpMethod =
(HttpMethod) msgContext.getProperty(HTTPConstants.HTTP_METHOD);
if (httpMethod != null) {
httpMethod.releaseConnection();
}
}
public void init(ConfigurationContext confContext,
TransportOutDescription transportOut)
throws AxisFault {
// <parameter name="PROTOCOL" locked="false">HTTP/1.0</parameter> or
// <parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter> is
// checked
Parameter version =
transportOut.getParameter(HTTPConstants.PROTOCOL_VERSION);
if (version != null) {
if (HTTPConstants.HEADER_PROTOCOL_11.equals(version.getValue())) {
httpVersion = HTTPConstants.HEADER_PROTOCOL_11;
Parameter transferEncoding =
transportOut.getParameter(
HTTPConstants.HEADER_TRANSFER_ENCODING);
if ((transferEncoding != null)
&&
HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED.equals(
transferEncoding.getValue())) {
chunked = true;
}
} else if (HTTPConstants.HEADER_PROTOCOL_10.equals(version.getValue())) {
httpVersion = HTTPConstants.HEADER_PROTOCOL_10;
} else {
throw new AxisFault(
"Parameter " + HTTPConstants.PROTOCOL_VERSION
+ " Can have values only HTTP/1.0 or HTTP/1.1");
}
}
// Get the timeout values from the configuration
try {
Parameter tempSoTimeoutParam =
transportOut.getParameter(HTTPConstants.SO_TIMEOUT);
Parameter tempConnTimeoutParam =
transportOut.getParameter(HTTPConstants.CONNECTION_TIMEOUT);
if (tempSoTimeoutParam != null) {
soTimeout = Integer.parseInt(
(String) tempSoTimeoutParam.getValue());
}
if (tempConnTimeoutParam != null) {
connectionTimeout = Integer.parseInt(
(String) tempConnTimeoutParam.getValue());
}
} catch (NumberFormatException nfe) {
// If there's a problem log it and use the default values
log.error("Invalid timeout value format: not a number", nfe);
}
}
public void stop() {
// Any code that , need to invoke when sender stop
}
public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
try {
OMOutputFormat format = new OMOutputFormat();
String charSetEnc =
(String) msgContext
.getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
if (charSetEnc != null) {
format.setCharSetEncoding(charSetEnc);
} else {
OperationContext opctx = msgContext.getOperationContext();
if (opctx != null) {
charSetEnc = (String) opctx
.getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
}
}
/**
* If the char set enc is still not found use the default
*/
if (charSetEnc == null) {
charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
}
msgContext.setDoingMTOM(HTTPTransportUtils.doWriteMTOM(msgContext));
msgContext.setDoingSwA(HTTPTransportUtils.doWriteSwA(msgContext));
msgContext.setDoingREST(HTTPTransportUtils.isDoingREST(msgContext));
format.setSOAP11(msgContext.isSOAP11());
format.setDoOptimize(msgContext.isDoingMTOM());
format.setDoingSWA(msgContext.isDoingSwA());
format.setCharSetEncoding(charSetEnc);
// Trasnport URL can be different from the WSA-To. So processing
// that now.
EndpointReference epr = null;
String transportURL =
(String) msgContext
.getProperty(Constants.Configuration.TRANSPORT_URL);
if (transportURL != null) {
epr = new EndpointReference(transportURL);
} else if (msgContext.getTo() != null && !msgContext.getTo().hasAnonymousAddress()) {
epr = msgContext.getTo();
}
// Check for the REST behaviour, if you desire rest beahaviour
// put a <parameter name="doREST" value="true"/> at the
// server.xml/client.xml file
// ######################################################
// Change this place to change the wsa:toepr
// epr = something
// ######################################################
OMElement dataOut;
/**
* Figuringout the REST properties/parameters
*/
if (msgContext.isDoingREST()) {
dataOut = msgContext.getEnvelope().getBody().getFirstElement();
} else {
dataOut = msgContext.getEnvelope();
}
if (epr != null) {
if (!epr.hasNoneAddress()) {
writeMessageWithCommons(msgContext, epr, dataOut, format);
}
} else {
if (msgContext.getProperty(MessageContext.TRANSPORT_OUT) != null) {
sendUsingOutputStream(msgContext, format, dataOut);
} else {
throw new AxisFault("Both the TO and Property MessageContext.TRANSPORT_OUT is Null, No where to send");
}
}
if (msgContext.getOperationContext() != null) {
msgContext.getOperationContext()
.setProperty(Constants.RESPONSE_WRITTEN,
Constants.VALUE_TRUE);
}
} catch (XMLStreamException e) {
log.debug(e);
throw new AxisFault(e);
} catch (FactoryConfigurationError e) {
log.debug(e);
throw new AxisFault(e);
} catch (IOException e) {
log.debug(e);
throw new AxisFault(e);
}
return InvocationResponse.CONTINUE;
}
private void sendUsingOutputStream(MessageContext msgContext,
OMOutputFormat format,
OMElement dataOut) throws AxisFault, XMLStreamException {
OutputStream out =
(OutputStream) msgContext
.getProperty(MessageContext.TRANSPORT_OUT);
if (msgContext.isServerSide()) {
OutTransportInfo transportInfo =
(OutTransportInfo) msgContext
.getProperty(Constants.OUT_TRANSPORT_INFO);
if (transportInfo != null) {
String contentType;
Object contentTypeObject = msgContext.getProperty(Constants.Configuration.CONTENT_TYPE);
if (contentTypeObject != null) {
contentType = (String) contentTypeObject;
} else if (msgContext.isDoingREST() && !(format.isOptimized())) {
contentType = HTTPConstants.MEDIA_TYPE_APPLICATION_XML;
} else {
contentType = format.getContentType();
format.setSOAP11(msgContext.isSOAP11());
}
String encoding = contentType + "; charset="
+ format.getCharSetEncoding();
transportInfo.setContentType(encoding);
} else {
throw new AxisFault(Constants.OUT_TRANSPORT_INFO +
" has not been set");
}
}
format.setDoOptimize(msgContext.isDoingMTOM());
format.setDoingSWA(msgContext.isDoingSwA());
format.setAutoCloseWriter(true);
if (!(msgContext.isDoingMTOM()) & (msgContext.isDoingSwA())
& !(msgContext.isDoingREST())) {
StringWriter bufferedSOAPBody = new StringWriter();
dataOut.serializeAndConsume(bufferedSOAPBody, format);
MIMEOutputUtils.writeSOAPWithAttachmentsMessage(bufferedSOAPBody,
out, msgContext.getAttachmentMap(), format);
} else {
dataOut.serializeAndConsume(out, format);
}
}
public void writeMessageWithCommons(MessageContext messageContext,
EndpointReference toEPR,
OMElement dataout,
OMOutputFormat format)
throws AxisFault {
try {
URL url = new URL(toEPR.getAddress());
String soapActionString = "\"\"";
Object disableSoapAction =
messageContext.getOptions().getProperty(Constants.Configuration.DISABLE_SOAP_ACTION);
if (!JavaUtils.isTrueExplicitly(disableSoapAction)) {
// first try to get the SOAP action from message context
soapActionString = messageContext.getSoapAction();
if ((soapActionString == null) || (soapActionString.length() == 0)) {
// now let's try to get WSA action
soapActionString = messageContext.getWSAAction();
if (messageContext.getAxisOperation() != null && ((soapActionString == null) || (soapActionString.length() == 0))) {
// last option is to get it from the axis operation
soapActionString = messageContext.getAxisOperation().getSoapAction();
}
}
}
if (soapActionString == null) {
soapActionString = "\"\"";
}
// select the Message Sender depending on the REST status
AbstractHTTPSender sender;
if (!messageContext.isDoingREST()) {
sender = new SOAPOverHTTPSender();
} else {
sender = new RESTSender();
}
if (messageContext.getProperty(HTTPConstants.CHUNKED) != null) {
chunked = JavaUtils.isTrueExplicitly(messageContext.getProperty(
HTTPConstants.CHUNKED));
}
if (messageContext.getProperty(HTTPConstants.HTTP_PROTOCOL_VERSION) != null) {
httpVersion = (String) messageContext.getProperty(HTTPConstants.HTTP_PROTOCOL_VERSION);
}
// Following order needed to be preserved because,
// HTTP/1.0 does not support chunk encoding
sender.setChunked(chunked);
sender.setHttpVersion(httpVersion);
sender.setFormat(format);
sender.send(messageContext, dataout, url, soapActionString);
} catch (MalformedURLException e) {
log.debug(e);
throw new AxisFault(e);
} catch (HttpException e) {
log.debug(e);
throw new AxisFault(e);
} catch (IOException e) {
log.debug(e);
throw new AxisFault(e);
}
}
public void writeMessageWithToOutPutStream(MessageContext msgContext,
OutputStream out) {
}
}