blob: 566db64b212221b31497acefdef400c86796706d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.impl.httpclient3;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import javax.xml.namespace.QName;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.NamedValue;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.MessageFormatter;
import org.apache.axis2.transport.TransportUtils;
import org.apache.axis2.transport.http.HTTPAuthenticator;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HTTPSender;
import org.apache.axis2.transport.http.HTTPTransportConstants;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HeaderElement;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.protocol.HTTP;
public class HTTPSenderImpl extends HTTPSender {
private static final Log log = LogFactory.getLog(HTTPSenderImpl.class);
/**
* Used to send a request via HTTP Get method
*
* @param msgContext
* - The MessageContext of the message
* @param url
* - The target URL
* @param soapActiionString
* - The soapAction string of the request
* @throws AxisFault
* - Thrown in case an exception occurs
*/
protected void sendViaGet(MessageContext msgContext, URL url, String soapActiionString)
throws AxisFault {
GetMethod getMethod = new GetMethod();
HttpClient httpClient = getHttpClient(msgContext);
MessageFormatter messageFormatter = populateCommonProperties(msgContext, url, getMethod,
httpClient, soapActiionString);
// Need to have this here because we can have soap action when using the
// soap response MEP
String soapAction = messageFormatter
.formatSOAPAction(msgContext, format, soapActiionString);
if (soapAction != null) {
getMethod.setRequestHeader(HTTPConstants.HEADER_SOAP_ACTION, soapAction);
}
try {
executeMethod(httpClient, msgContext, url, getMethod);
handleResponse(msgContext, getMethod);
} catch (IOException e) {
log.info("Unable to sendViaGet to url[" + url + "]", e);
throw AxisFault.makeFault(e);
} finally {
cleanup(msgContext, getMethod);
}
}
protected void cleanup(MessageContext msgContext, Object httpMmethod) {
if (httpMmethod instanceof HttpMethod) {
if (msgContext.isPropertyTrue(HTTPConstants.AUTO_RELEASE_CONNECTION)) {
log.trace("AutoReleasing " + httpMmethod);
((HttpMethod) httpMmethod).releaseConnection();
}
}
}
/**
* Used to send a request via HTTP Delete Method
*
* @param msgContext
* - The MessageContext of the message
* @param url
* - The target URL
* @param soapActiionString
* - The soapAction string of the request
* @throws AxisFault
* - Thrown in case an exception occurs
*/
protected void sendViaDelete(MessageContext msgContext, URL url, String soapActiionString)
throws AxisFault {
DeleteMethod deleteMethod = new DeleteMethod();
HttpClient httpClient = getHttpClient(msgContext);
populateCommonProperties(msgContext, url, deleteMethod, httpClient, soapActiionString);
try {
executeMethod(httpClient, msgContext, url, deleteMethod);
handleResponse(msgContext, deleteMethod);
} catch (IOException e) {
log.info("Unable to sendViaDelete to url[" + url + "]", e);
throw AxisFault.makeFault(e);
} finally {
cleanup(msgContext, deleteMethod);
}
}
/**
* Used to send a request via HTTP Post Method
*
* @param msgContext
* - The MessageContext of the message
* @param url
* - The target URL
* @param soapActionString
* - The soapAction string of the request
* @throws AxisFault
* - Thrown in case an exception occurs
*/
protected void sendViaPost(MessageContext msgContext, URL url, String soapActionString)
throws AxisFault {
HttpClient httpClient = getHttpClient(msgContext);
/*
* What's up with this, it never gets used anywhere?? --Glen String
* charEncoding = (String)
* msgContext.getProperty(Constants.Configuration
* .CHARACTER_SET_ENCODING);
*
* if (charEncoding == null) { charEncoding =
* MessageContext.DEFAULT_CHAR_SET_ENCODING; }
*/
PostMethod postMethod = new PostMethod();
if (log.isTraceEnabled()) {
log.trace(Thread.currentThread() + " PostMethod " + postMethod + " / " + httpClient);
}
MessageFormatter messageFormatter = populateCommonProperties(msgContext, url, postMethod,
httpClient, soapActionString);
postMethod.setRequestEntity(new AxisRequestEntityImpl(messageFormatter, msgContext, format,
soapActionString, chunked, isAllowedRetry));
if (!httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_10) && chunked) {
postMethod.setContentChunked(true);
}
String soapAction = messageFormatter.formatSOAPAction(msgContext, format, soapActionString);
if (soapAction != null) {
postMethod.setRequestHeader(HTTPConstants.HEADER_SOAP_ACTION, soapAction);
}
/*
* main excecution takes place..
*/
try {
executeMethod(httpClient, msgContext, url, postMethod);
handleResponse(msgContext, postMethod);
} catch (IOException e) {
log.info("Unable to sendViaPost to url[" + url + "]", e);
throw AxisFault.makeFault(e);
} finally {
cleanup(msgContext, postMethod);
}
}
/**
* Used to send a request via HTTP Put Method
*
* @param msgContext
* - The MessageContext of the message
* @param url
* - The target URL
* @param soapActionString
* - The soapAction string of the request
* @throws AxisFault
* - Thrown in case an exception occurs
*/
protected void sendViaPut(MessageContext msgContext, URL url, String soapActionString)
throws AxisFault {
HttpClient httpClient = getHttpClient(msgContext);
/*
* Same deal - this value never gets used, why is it here? --Glen String
* charEncoding = (String)
* msgContext.getProperty(Constants.Configuration
* .CHARACTER_SET_ENCODING);
*
* if (charEncoding == null) { charEncoding =
* MessageContext.DEFAULT_CHAR_SET_ENCODING; }
*/
PutMethod putMethod = new PutMethod();
MessageFormatter messageFormatter = populateCommonProperties(msgContext, url, putMethod,
httpClient, soapActionString);
putMethod.setRequestEntity(new AxisRequestEntityImpl(messageFormatter, msgContext, format,
soapActionString, chunked, isAllowedRetry));
if (!httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_10) && chunked) {
putMethod.setContentChunked(true);
}
String soapAction = messageFormatter.formatSOAPAction(msgContext, format, soapActionString);
if (soapAction != null) {
putMethod.setRequestHeader(HTTPConstants.HEADER_SOAP_ACTION, soapAction);
}
/*
* main excecution takes place..
*/
try {
executeMethod(httpClient, msgContext, url, putMethod);
handleResponse(msgContext, putMethod);
} catch (IOException e) {
log.info("Unable to sendViaPut to url[" + url + "]", e);
throw AxisFault.makeFault(e);
} finally {
cleanup(msgContext, putMethod);
}
}
/**
* Used to handle the HTTP Response
*
* @param msgContext
* - The MessageContext of the message
* @param method
* - The HTTP method used
* @throws IOException
* - Thrown in case an exception occurs
*/
protected void handleResponse(MessageContext msgContext, Object httpMethodBase)
throws IOException {
HttpMethodBase method;
if (httpMethodBase instanceof HttpMethodBase) {
method = (HttpMethodBase) httpMethodBase;
} else {
log.trace("HttpMethodBase expected, but found - " + httpMethodBase);
return;
}
int statusCode = method.getStatusCode();
HTTPStatusCodeFamily family = getHTTPStatusCodeFamily(statusCode);
log.trace("Handling response - " + statusCode);
if (statusCode == HttpStatus.SC_ACCEPTED) {
/* When an HTTP 202 Accepted code has been received, this will be the case of an execution
* of an in-only operation. In such a scenario, the HTTP response headers should be returned,
* i.e. session cookies. */
obtainHTTPHeaderInformation(method, msgContext);
// Since we don't expect any content with a 202 response, we must release the connection
method.releaseConnection();
} else if (HTTPStatusCodeFamily.SUCCESSFUL.equals(family)) {
// Save the HttpMethod so that we can release the connection when cleaning up
msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
processResponse(method, msgContext);
} else if (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR
|| statusCode == HttpStatus.SC_BAD_REQUEST) {
// Save the HttpMethod so that we can release the connection when
// cleaning up
msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
Header contenttypeHeader = method.getResponseHeader(HTTPConstants.HEADER_CONTENT_TYPE);
String value = null;
if (contenttypeHeader != null) {
value = contenttypeHeader.getValue();
}
OperationContext opContext = msgContext.getOperationContext();
if (opContext != null) {
MessageContext inMessageContext = opContext
.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (inMessageContext != null) {
inMessageContext.setProcessingFault(true);
}
}
if (value != null) {
processResponse(method, msgContext);
}
if (org.apache.axis2.util.Utils.isClientThreadNonBlockingPropertySet(msgContext)) {
throw new AxisFault(Messages.getMessage("transportError",
String.valueOf(statusCode), method.getStatusText()));
}
} else {
// Since we don't process the response, we must release the
// connection immediately
method.releaseConnection();
throw new AxisFault(Messages.getMessage("transportError", String.valueOf(statusCode),
method.getStatusText()));
}
}
/**
* Collect the HTTP header information and set them in the message context
*
* @param method
* HttpMethodBase from which to get information
* @param msgContext
* the MessageContext in which to place the information... OR
* NOT!
* @throws AxisFault
* if problems occur
*/
protected void obtainHTTPHeaderInformation(Object httpMethodBase, MessageContext msgContext)
throws AxisFault {
HttpMethod method;
if (httpMethodBase instanceof HttpMethodBase) {
method = (HttpMethod) httpMethodBase;
} else {
return;
}
// Set RESPONSE properties onto the REQUEST message context. They will
// need to be copied off the request context onto
// the response context elsewhere, for example in the
// OutInOperationClient.
Map transportHeaders = new HTTPTransportHeaders(method.getResponseHeaders());
msgContext.setProperty(MessageContext.TRANSPORT_HEADERS, transportHeaders);
msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE,
new Integer(method.getStatusCode()));
Header header = method.getResponseHeader(HTTPConstants.HEADER_CONTENT_TYPE);
if (header != null) {
HeaderElement[] headers = header.getElements();
MessageContext inMessageContext = msgContext.getOperationContext().getMessageContext(
WSDLConstants.MESSAGE_LABEL_IN_VALUE);
Object contentType = header.getValue();
Object charSetEnc = null;
for (int i = 0; i < headers.length; i++) {
NameValuePair charsetEnc = headers[i]
.getParameterByName(HTTPConstants.CHAR_SET_ENCODING);
if (charsetEnc != null) {
charSetEnc = charsetEnc.getValue();
}
}
if (inMessageContext != null) {
inMessageContext.setProperty(Constants.Configuration.CONTENT_TYPE, contentType);
inMessageContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING,
charSetEnc);
} else {
// Transport details will be stored in a HashMap so that anybody
// interested can
// retrieve them
HashMap transportInfoMap = new HashMap();
transportInfoMap.put(Constants.Configuration.CONTENT_TYPE, contentType);
transportInfoMap.put(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEnc);
// the HashMap is stored in the outgoing message.
msgContext
.setProperty(Constants.Configuration.TRANSPORT_INFO_MAP, transportInfoMap);
}
}
String sessionCookie = null;
// Process old style headers first
Header[] cookieHeaders = method.getResponseHeaders(HTTPConstants.HEADER_SET_COOKIE);
String customCoookiId = (String) msgContext.getProperty(Constants.CUSTOM_COOKIE_ID);
for (int i = 0; i < cookieHeaders.length; i++) {
HeaderElement[] elements = cookieHeaders[i].getElements();
for (int e = 0; e < elements.length; e++) {
HeaderElement element = elements[e];
if (Constants.SESSION_COOKIE.equalsIgnoreCase(element.getName())
|| Constants.SESSION_COOKIE_JSESSIONID.equalsIgnoreCase(element.getName())) {
sessionCookie = processCookieHeader(element);
}
if (customCoookiId != null && customCoookiId.equalsIgnoreCase(element.getName())) {
sessionCookie = processCookieHeader(element);
}
}
}
// Overwrite old style cookies with new style ones if present
cookieHeaders = method.getResponseHeaders(HTTPConstants.HEADER_SET_COOKIE2);
for (int i = 0; i < cookieHeaders.length; i++) {
HeaderElement[] elements = cookieHeaders[i].getElements();
for (int e = 0; e < elements.length; e++) {
HeaderElement element = elements[e];
if (Constants.SESSION_COOKIE.equalsIgnoreCase(element.getName())
|| Constants.SESSION_COOKIE_JSESSIONID.equalsIgnoreCase(element.getName())) {
sessionCookie = processCookieHeader(element);
}
if (customCoookiId != null && customCoookiId.equalsIgnoreCase(element.getName())) {
sessionCookie = processCookieHeader(element);
}
}
}
if (sessionCookie != null) {
msgContext.getServiceContext().setProperty(HTTPConstants.COOKIE_STRING, sessionCookie);
}
}
private String processCookieHeader(HeaderElement element) {
String cookie = element.getName() + "=" + element.getValue();
NameValuePair[] parameters = element.getParameters();
for (int j = 0; parameters != null && j < parameters.length; j++) {
NameValuePair parameter = parameters[j];
cookie = cookie + "; " + parameter.getName() + "=" + parameter.getValue();
}
return cookie;
}
protected void processResponse(HttpMethodBase httpMethod, MessageContext msgContext)
throws IOException {
obtainHTTPHeaderInformation(httpMethod, msgContext);
InputStream in = httpMethod.getResponseBodyAsStream();
if (in == null) {
throw new AxisFault(Messages.getMessage("canNotBeNull", "InputStream"));
}
Header contentEncoding = httpMethod
.getResponseHeader(HTTPConstants.HEADER_CONTENT_ENCODING);
if (contentEncoding != null) {
if (contentEncoding.getValue().equalsIgnoreCase(HTTPConstants.COMPRESSION_GZIP)) {
in = new GZIPInputStream(in);
// If the content-encoding is identity we can basically ignore
// it.
} else if (!"identity".equalsIgnoreCase(contentEncoding.getValue())) {
throw new AxisFault("HTTP :" + "unsupported content-encoding of '"
+ contentEncoding.getValue() + "' found");
}
}
OperationContext opContext = msgContext.getOperationContext();
if (opContext != null) {
opContext.setProperty(MessageContext.TRANSPORT_IN, in);
}
}
/**
* getting host configuration to support standard http/s, proxy and NTLM
* support
*
* @param client
* active HttpClient
* @param msgCtx
* active MessageContext
* @param targetURL
* the target URL
* @return a HostConfiguration set up with proxy information
* @throws AxisFault
* if problems occur
*/
protected HostConfiguration getHostConfiguration(HttpClient client, MessageContext msgCtx,
URL targetURL) throws AxisFault {
boolean isAuthenticationEnabled = isAuthenticationEnabled(msgCtx);
int port = targetURL.getPort();
String protocol = targetURL.getProtocol();
if (port == -1) {
if (HTTPTransportConstants.PROTOCOL_HTTP.equals(protocol)) {
port = 80;
} else if (HTTPTransportConstants.PROTOCOL_HTTPS.equals(protocol)) {
port = 443;
}
}
// to see the host is a proxy and in the proxy list - available in
// axis2.xml
HostConfiguration config = new HostConfiguration();
// one might need to set his own socket factory. Let's allow that case
// as well.
Protocol protocolHandler = (Protocol) msgCtx.getOptions().getProperty(
HTTPConstants.CUSTOM_PROTOCOL_HANDLER);
// setting the real host configuration
// I assume the 90% case, or even 99% case will be no protocol handler
// case.
if (protocolHandler == null) {
config.setHost(targetURL.getHost(), port, targetURL.getProtocol());
} else {
config.setHost(targetURL.getHost(), port, protocolHandler);
}
if (isAuthenticationEnabled) {
// Basic, Digest, NTLM and custom authentications.
this.setAuthenticationInfo(client, msgCtx, config);
}
// proxy configuration
if (HTTPProxyConfigurator.isProxyEnabled(msgCtx, targetURL)) {
if (log.isDebugEnabled()) {
log.debug("Configuring HTTP proxy.");
}
HTTPProxyConfigurator.configure(msgCtx, client, config);
}
return config;
}
protected boolean isAuthenticationEnabled(MessageContext msgCtx) {
return (msgCtx.getProperty(HTTPConstants.AUTHENTICATE) != null);
}
/*
* This will handle server Authentication, It could be either NTLM, Digest
* or Basic Authentication. Apart from that user can change the priory or
* add a custom authentication scheme.
*/
protected void setAuthenticationInfo(HttpClient agent, MessageContext msgCtx,
HostConfiguration config) throws AxisFault {
HTTPAuthenticator authenticator;
Object obj = msgCtx.getProperty(HTTPConstants.AUTHENTICATE);
if (obj != null) {
if (obj instanceof HTTPAuthenticator) {
authenticator = (HTTPAuthenticator) obj;
String username = authenticator.getUsername();
String password = authenticator.getPassword();
String host = authenticator.getHost();
String domain = authenticator.getDomain();
int port = authenticator.getPort();
String realm = authenticator.getRealm();
/* If retrying is available set it first */
isAllowedRetry = authenticator.isAllowedRetry();
Credentials creds;
HttpState tmpHttpState = null;
HttpState httpState = (HttpState) msgCtx
.getProperty(HTTPConstants.CACHED_HTTP_STATE);
if (httpState != null) {
tmpHttpState = httpState;
} else {
tmpHttpState = agent.getState();
}
agent.getParams().setAuthenticationPreemptive(
authenticator.getPreemptiveAuthentication());
if (host != null) {
if (domain != null) {
/* Credentials for NTLM Authentication */
creds = new NTCredentials(username, password, host, domain);
} else {
/* Credentials for Digest and Basic Authentication */
creds = new UsernamePasswordCredentials(username, password);
}
tmpHttpState.setCredentials(new AuthScope(host, port, realm), creds);
} else {
if (domain != null) {
/*
* Credentials for NTLM Authentication when host is
* ANY_HOST
*/
creds = new NTCredentials(username, password, AuthScope.ANY_HOST, domain);
tmpHttpState.setCredentials(new AuthScope(AuthScope.ANY_HOST, port, realm),
creds);
} else {
/* Credentials only for Digest and Basic Authentication */
creds = new UsernamePasswordCredentials(username, password);
tmpHttpState.setCredentials(new AuthScope(AuthScope.ANY), creds);
}
}
/* Customizing the priority Order */
List schemes = authenticator.getAuthSchemes();
if (schemes != null && schemes.size() > 0) {
List authPrefs = new ArrayList(3);
for (int i = 0; i < schemes.size(); i++) {
if (schemes.get(i) instanceof AuthPolicy) {
authPrefs.add(schemes.get(i));
continue;
}
String scheme = (String) schemes.get(i);
authPrefs.add(authenticator.getAuthPolicyPref(scheme));
}
agent.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
}
} else {
throw new AxisFault("HttpTransportProperties.Authenticator class cast exception");
}
}
}
/**
* Method used to copy all the common properties
*
* @param msgContext
* - The messageContext of the request message
* @param url
* - The target URL
* @param httpMethod
* - The http method used to send the request
* @param httpClient
* - The httpclient used to send the request
* @param soapActionString
* - The soap action atring of the request message
* @return MessageFormatter - The messageFormatter for the relavent request
* message
* @throws AxisFault
* - Thrown in case an exception occurs
*/
protected MessageFormatter populateCommonProperties(MessageContext msgContext, URL url,
HttpMethodBase httpMethod, HttpClient httpClient, String soapActionString)
throws AxisFault {
if (isAuthenticationEnabled(msgContext)) {
httpMethod.setDoAuthentication(true);
}
MessageFormatter messageFormatter = TransportUtils.getMessageFormatter(msgContext);
url = messageFormatter.getTargetAddress(msgContext, format, url);
httpMethod.setPath(url.getPath());
httpMethod.setQueryString(url.getQuery());
httpMethod.setRequestHeader(HTTPConstants.HEADER_CONTENT_TYPE,
messageFormatter.getContentType(msgContext, format, soapActionString));
httpMethod.setRequestHeader(HTTPConstants.HEADER_HOST, url.getHost());
if (msgContext.getOptions() != null && msgContext.getOptions().isManageSession()) {
// setting the cookie in the out path
Object cookieString = msgContext.getProperty(HTTPConstants.COOKIE_STRING);
if (cookieString != null) {
StringBuffer buffer = new StringBuffer();
buffer.append(cookieString);
httpMethod.setRequestHeader(HTTPConstants.HEADER_COOKIE, buffer.toString());
}
}
if (httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_10)) {
httpClient.getParams().setVersion(HttpVersion.HTTP_1_0);
}
return messageFormatter;
}
/**
* This is used to get the dynamically set time out values from the message
* context. If the values are not available or invalid then the default
* values or the values set by the configuration will be used
*
* @param msgContext
* the active MessageContext
* @param httpClient
*/
protected void initializeTimeouts(MessageContext msgContext, HttpClient httpClient) {
// If the SO_TIMEOUT of CONNECTION_TIMEOUT is set by dynamically the
// override the static config
Integer tempSoTimeoutProperty = (Integer) msgContext.getProperty(HTTPConstants.SO_TIMEOUT);
Integer tempConnTimeoutProperty = (Integer) msgContext
.getProperty(HTTPConstants.CONNECTION_TIMEOUT);
long timeout = msgContext.getOptions().getTimeOutInMilliSeconds();
if (tempConnTimeoutProperty != null) {
int connectionTimeout = tempConnTimeoutProperty.intValue();
// timeout for initial connection
httpClient.getHttpConnectionManager().getParams()
.setConnectionTimeout(connectionTimeout);
} else {
// set timeout in client
if (timeout > 0) {
httpClient.getHttpConnectionManager().getParams()
.setConnectionTimeout((int) timeout);
}
}
if (tempSoTimeoutProperty != null) {
int soTimeout = tempSoTimeoutProperty.intValue();
// SO_TIMEOUT -- timeout for blocking reads
httpClient.getHttpConnectionManager().getParams().setSoTimeout(soTimeout);
httpClient.getParams().setSoTimeout(soTimeout);
} else {
// set timeout in client
if (timeout > 0) {
httpClient.getHttpConnectionManager().getParams().setSoTimeout((int) timeout);
httpClient.getParams().setSoTimeout((int) timeout);
}
}
}
/**
* This is used to get the dynamically set time out values from the message
* context. If the values are not available or invalid then the default
* values or the values set by the configuration will be used
*
* @param msgContext
* the active MessageContext
* @param httpMethod
* method
*/
protected void setTimeouts(MessageContext msgContext, HttpMethod httpMethod) {
// If the SO_TIMEOUT of CONNECTION_TIMEOUT is set by dynamically the
// override the static config
Integer tempSoTimeoutProperty = (Integer) msgContext.getProperty(HTTPConstants.SO_TIMEOUT);
Integer tempConnTimeoutProperty = (Integer) msgContext
.getProperty(HTTPConstants.CONNECTION_TIMEOUT);
long timeout = msgContext.getOptions().getTimeOutInMilliSeconds();
if (tempConnTimeoutProperty != null) {
// timeout for initial connection
httpMethod.getParams().setParameter("http.connection.timeout", tempConnTimeoutProperty);
}
if (tempSoTimeoutProperty != null) {
// SO_TIMEOUT -- timeout for blocking reads
httpMethod.getParams().setSoTimeout(tempSoTimeoutProperty);
} else {
// set timeout in client
if (timeout > 0) {
httpMethod.getParams().setSoTimeout((int) timeout);
}
}
}
protected HttpClient getHttpClient(MessageContext msgContext) {
ConfigurationContext configContext = msgContext.getConfigurationContext();
HttpClient httpClient = (HttpClient) msgContext
.getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
if (httpClient == null) {
httpClient = (HttpClient) configContext.getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
}
if (httpClient != null) {
return httpClient;
}
synchronized (this) {
httpClient = (HttpClient) msgContext.getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
if (httpClient == null) {
httpClient = (HttpClient) configContext
.getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
}
if (httpClient != null) {
return httpClient;
}
HttpConnectionManager connManager = (HttpConnectionManager) msgContext
.getProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER);
if (connManager == null) {
connManager = (HttpConnectionManager) msgContext
.getProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER);
}
if (connManager == null) {
// reuse HttpConnectionManager
synchronized (configContext) {
connManager = (HttpConnectionManager) configContext
.getProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER);
if (connManager == null) {
log.trace("Making new ConnectionManager");
connManager = new MultiThreadedHttpConnectionManager();
configContext.setProperty(
HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER, connManager);
}
}
}
/*
* Create a new instance of HttpClient since the way it is used here
* it's not fully thread-safe.
*/
httpClient = new HttpClient(connManager);
// Set the default timeout in case we have a connection pool
// starvation to 30sec
httpClient.getParams().setConnectionManagerTimeout(30000);
// Get the timeout values set in the runtime
initializeTimeouts(msgContext, httpClient);
return httpClient;
}
}
protected void executeMethod(HttpClient httpClient, MessageContext msgContext, URL url,
HttpMethod method) throws IOException {
HostConfiguration config = this.getHostConfiguration(httpClient, msgContext, url);
// set the custom headers, if available
addCustomHeaders(method, msgContext);
// add compression headers if needed
if (msgContext.isPropertyTrue(HTTPConstants.MC_ACCEPT_GZIP)) {
method.addRequestHeader(HTTPConstants.HEADER_ACCEPT_ENCODING,
HTTPConstants.COMPRESSION_GZIP);
}
if (msgContext.isPropertyTrue(HTTPConstants.MC_GZIP_REQUEST)) {
method.addRequestHeader(HTTPConstants.HEADER_CONTENT_ENCODING,
HTTPConstants.COMPRESSION_GZIP);
}
if (msgContext.getProperty(HTTPConstants.HTTP_METHOD_PARAMS) != null) {
HttpMethodParams params = (HttpMethodParams) msgContext
.getProperty(HTTPConstants.HTTP_METHOD_PARAMS);
method.setParams(params);
}
String cookiePolicy = (String) msgContext.getProperty(HTTPConstants.COOKIE_POLICY);
if (cookiePolicy != null) {
method.getParams().setCookiePolicy(cookiePolicy);
}
HttpState httpState = (HttpState) msgContext.getProperty(HTTPConstants.CACHED_HTTP_STATE);
setTimeouts(msgContext, method);
httpClient.executeMethod(config, method, httpState);
}
public void addCustomHeaders(HttpMethod method, MessageContext msgContext) {
boolean isCustomUserAgentSet = false;
// set the custom headers, if available
Object httpHeadersObj = msgContext.getProperty(HTTPConstants.HTTP_HEADERS);
if (httpHeadersObj != null) {
if (httpHeadersObj instanceof List) {
List httpHeaders = (List) httpHeadersObj;
for (int i = 0; i < httpHeaders.size(); i++) {
NamedValue nv = (NamedValue) httpHeaders.get(i);
if (nv != null) {
Header header = new Header(nv.getName(), nv.getValue());
if (HTTPConstants.HEADER_USER_AGENT.equals(header.getName())) {
isCustomUserAgentSet = true;
}
method.addRequestHeader(header);
}
}
}
if (httpHeadersObj instanceof Map) {
Map httpHeaders = (Map) httpHeadersObj;
for (Iterator iterator = httpHeaders.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (HTTPConstants.HEADER_USER_AGENT.equals(key)) {
isCustomUserAgentSet = true;
}
method.addRequestHeader(key, value);
}
}
}
// we have to consider the TRANSPORT_HEADERS map as well
Map transportHeaders = (Map) msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
if (transportHeaders != null) {
removeUnwantedHeaders(msgContext);
Set headerEntries = transportHeaders.entrySet();
for (Object headerEntry : headerEntries) {
if (headerEntry instanceof Map.Entry) {
Header[] headers = method.getRequestHeaders();
boolean headerAdded = false;
for (Header header : headers) {
if (header.getName() != null
&& header.getName().equals(((Map.Entry) headerEntry).getKey())) {
headerAdded = true;
break;
}
}
if (!headerAdded) {
method.addRequestHeader(((Map.Entry) headerEntry).getKey().toString(),
((Map.Entry) headerEntry).getValue().toString());
}
}
}
}
if (!isCustomUserAgentSet) {
String userAgentString = getUserAgent(msgContext);
method.setRequestHeader(HTTPConstants.HEADER_USER_AGENT, userAgentString);
}
}
/**
* Remove unwanted headers from the transport headers map of outgoing
* request. These are headers which should be dictated by the transport and
* not the user. We remove these as these may get copied from the request
* messages
*
* @param msgContext
* the Axis2 Message context from which these headers should be
* removed
*/
private void removeUnwantedHeaders(MessageContext msgContext) {
Map headers = (Map) msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
if (headers == null || headers.isEmpty()) {
return;
}
Iterator iter = headers.keySet().iterator();
while (iter.hasNext()) {
String headerName = (String) iter.next();
if (HTTP.CONN_DIRECTIVE.equalsIgnoreCase(headerName)
|| HTTP.TRANSFER_ENCODING.equalsIgnoreCase(headerName)
|| HTTP.DATE_HEADER.equalsIgnoreCase(headerName)
|| HTTP.CONTENT_TYPE.equalsIgnoreCase(headerName)
|| HTTP.CONTENT_LEN.equalsIgnoreCase(headerName)) {
iter.remove();
}
}
}
private String getUserAgent(MessageContext messageContext) {
String userAgentString = "Axis2";
boolean locked = false;
if (messageContext.getParameter(HTTPConstants.USER_AGENT) != null) {
OMElement userAgentElement = messageContext.getParameter(HTTPConstants.USER_AGENT)
.getParameterElement();
userAgentString = userAgentElement.getText().trim();
OMAttribute lockedAttribute = userAgentElement.getAttribute(new QName("locked"));
if (lockedAttribute != null) {
if (lockedAttribute.getAttributeValue().equalsIgnoreCase("true")) {
locked = true;
}
}
}
// Runtime overing part
if (!locked) {
if (messageContext.getProperty(HTTPConstants.USER_AGENT) != null) {
userAgentString = (String) messageContext.getProperty(HTTPConstants.USER_AGENT);
}
}
return userAgentString;
}
}