| /* |
| * 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.httpclient4; |
| |
| |
| 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.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.http.Header; |
| import org.apache.http.HeaderElement; |
| import org.apache.http.HttpEntity; |
| import org.apache.http.HttpHost; |
| import org.apache.http.HttpResponse; |
| import org.apache.http.HttpStatus; |
| import org.apache.http.HttpVersion; |
| import org.apache.http.NameValuePair; |
| import org.apache.http.auth.AuthScope; |
| import org.apache.http.auth.Credentials; |
| import org.apache.http.auth.NTCredentials; |
| import org.apache.http.auth.UsernamePasswordCredentials; |
| import org.apache.http.client.methods.HttpDelete; |
| import org.apache.http.client.methods.HttpGet; |
| import org.apache.http.client.methods.HttpPost; |
| import org.apache.http.client.methods.HttpPut; |
| import org.apache.http.client.methods.HttpRequestBase; |
| import org.apache.http.client.params.AuthPolicy; |
| import org.apache.http.client.params.ClientPNames; |
| import org.apache.http.conn.ClientConnectionManager; |
| import org.apache.http.conn.params.ConnManagerPNames; |
| import org.apache.http.conn.params.ConnPerRouteBean; |
| import org.apache.http.conn.scheme.PlainSocketFactory; |
| import org.apache.http.conn.scheme.Scheme; |
| import org.apache.http.conn.scheme.SchemeRegistry; |
| import org.apache.http.conn.ssl.SSLSocketFactory; |
| import org.apache.http.impl.client.AbstractHttpClient; |
| import org.apache.http.impl.client.DefaultHttpClient; |
| import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; |
| import org.apache.http.message.BasicHeader; |
| import org.apache.http.params.BasicHttpParams; |
| import org.apache.http.params.CoreConnectionPNames; |
| import org.apache.http.params.CoreProtocolPNames; |
| import org.apache.http.params.HttpParams; |
| import org.apache.http.protocol.BasicHttpContext; |
| import org.apache.http.protocol.HTTP; |
| import org.apache.http.protocol.HttpContext; |
| |
| import javax.xml.namespace.QName; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URISyntaxException; |
| 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; |
| |
| |
| 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 soapActionString - The soapAction string of the request |
| * @throws org.apache.axis2.AxisFault - Thrown in case an exception occurs |
| */ |
| protected void sendViaGet(MessageContext msgContext, URL url, String soapActionString) |
| throws AxisFault { |
| HttpGet httpGet = new HttpGet(); |
| AbstractHttpClient httpClient = getHttpClient(msgContext); |
| MessageFormatter messageFormatter = populateCommonProperties(msgContext, url, httpGet, |
| httpClient, soapActionString); |
| |
| // Need to have this here because we can have soap action when using the |
| // soap response MEP |
| String soapAction = messageFormatter |
| .formatSOAPAction(msgContext, format, soapActionString); |
| |
| if (soapAction != null) { |
| httpGet.setHeader(HTTPConstants.HEADER_SOAP_ACTION, soapAction); |
| } |
| |
| /* |
| * main execution takes place.. |
| */ |
| HttpResponse response = null; |
| try { |
| response = executeMethod(httpClient, msgContext, url, httpGet); |
| handleResponse(msgContext, response); |
| } catch (IOException e) { |
| log.info("Unable to sendViaGet to url[" + url + "]", e); |
| throw AxisFault.makeFault(e); |
| } finally { |
| cleanup(msgContext, response); |
| } |
| } |
| |
| @Override |
| protected void cleanup(MessageContext msgContext, Object httpResponse) { |
| HttpResponse response; |
| if (httpResponse instanceof HttpResponse) { |
| response = (HttpResponse) httpResponse; |
| } else { |
| log.trace("HttpResponse expected, but found - " + httpResponse); |
| return; |
| } |
| log.trace("Cleaning response : " + response); |
| HttpEntity entity = response.getEntity(); |
| if (entity != null && entity.isStreaming()) { |
| InputStream inputStream; |
| try { |
| inputStream = entity.getContent(); |
| if (inputStream != null) { |
| inputStream.close(); |
| } |
| } catch (IOException e) { |
| log.error("Error while cleaning response : "+response, e); |
| } |
| } |
| } |
| |
| /** |
| * Used to send a request via HTTP Delete Method |
| * |
| * @param msgContext - The MessageContext of the message |
| * @param url - The target URL |
| * @param soapActionString - The soapAction string of the request |
| * @throws org.apache.axis2.AxisFault - Thrown in case an exception occurs |
| */ |
| protected void sendViaDelete(MessageContext msgContext, URL url, String soapActionString) |
| throws AxisFault { |
| |
| HttpDelete deleteMethod = new HttpDelete(); |
| AbstractHttpClient httpClient = getHttpClient(msgContext); |
| populateCommonProperties(msgContext, url, deleteMethod, httpClient, soapActionString); |
| |
| /* |
| * main execution takes place.. |
| */ |
| HttpResponse response = null; |
| try { |
| response = executeMethod(httpClient, msgContext, url, deleteMethod); |
| handleResponse(msgContext, response); |
| } catch (IOException e) { |
| log.info("Unable to sendViaDelete to url[" + url + "]", e); |
| throw AxisFault.makeFault(e); |
| } finally { |
| cleanup(msgContext, response); |
| } |
| } |
| |
| /** |
| * 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 org.apache.axis2.AxisFault - Thrown in case an exception occurs |
| */ |
| protected void sendViaPost(MessageContext msgContext, URL url, String soapActionString) |
| throws AxisFault { |
| |
| AbstractHttpClient 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; } |
| */ |
| |
| HttpPost postMethod = new HttpPost(); |
| if (log.isTraceEnabled()) { |
| log.trace(Thread.currentThread() + " PostMethod " + postMethod + " / " + httpClient); |
| } |
| MessageFormatter messageFormatter = populateCommonProperties(msgContext, url, postMethod, |
| httpClient, soapActionString); |
| AxisRequestEntityImpl requestEntity = |
| new AxisRequestEntityImpl(messageFormatter, msgContext, format, |
| soapActionString, chunked, isAllowedRetry); |
| postMethod.setEntity(requestEntity); |
| |
| if (!httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_10) && chunked) { |
| requestEntity.setChunked(chunked); |
| } |
| |
| String soapAction = messageFormatter.formatSOAPAction(msgContext, format, soapActionString); |
| |
| if (soapAction != null) { |
| postMethod.setHeader(HTTPConstants.HEADER_SOAP_ACTION, soapAction); |
| } |
| |
| /* |
| * main execution takes place.. |
| */ |
| HttpResponse response = null; |
| try { |
| response = executeMethod(httpClient, msgContext, url, postMethod); |
| handleResponse(msgContext, response); |
| } catch (IOException e) { |
| log.info("Unable to sendViaPost to url[" + url + "]", e); |
| throw AxisFault.makeFault(e); |
| } finally { |
| cleanup(msgContext, response); |
| } |
| } |
| |
| /** |
| * 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 org.apache.axis2.AxisFault - Thrown in case an exception occurs |
| */ |
| protected void sendViaPut(MessageContext msgContext, URL url, String soapActionString) |
| throws AxisFault { |
| |
| AbstractHttpClient 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; } |
| */ |
| |
| HttpPut putMethod = new HttpPut(); |
| MessageFormatter messageFormatter = populateCommonProperties(msgContext, url, putMethod, |
| httpClient, soapActionString); |
| AxisRequestEntityImpl requestEntity = |
| new AxisRequestEntityImpl(messageFormatter, msgContext, format, |
| soapActionString, chunked, isAllowedRetry); |
| putMethod.setEntity(requestEntity); |
| |
| if (!httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_10) && chunked) { |
| requestEntity.setChunked(chunked); |
| } |
| |
| String soapAction = messageFormatter.formatSOAPAction(msgContext, format, soapActionString); |
| if (soapAction != null) { |
| putMethod.setHeader(HTTPConstants.HEADER_SOAP_ACTION, soapAction); |
| } |
| |
| /* |
| * main execution takes place.. |
| */ |
| HttpResponse response = null; |
| try { |
| response = executeMethod(httpClient, msgContext, url, putMethod); |
| handleResponse(msgContext, response); |
| } catch (IOException e) { |
| log.info("Unable to sendViaPut to url[" + url + "]", e); |
| throw AxisFault.makeFault(e); |
| } finally { |
| cleanup(msgContext, response); |
| } |
| } |
| |
| /** |
| * Used to handle the HTTP Response |
| * |
| * @param msgContext - The MessageContext of the message |
| * @param - The HTTP method used |
| * @throws java.io.IOException - Thrown in case an exception occurs |
| */ |
| protected void handleResponse(MessageContext msgContext, Object httpResponse) |
| throws IOException { |
| HttpResponse response; |
| if (httpResponse instanceof HttpResponse) { |
| response = (HttpResponse) httpResponse; |
| } else { |
| log.trace("HttpResponse expected, but found - " + httpResponse); |
| return; |
| } |
| int statusCode = response.getStatusLine().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(response, msgContext); |
| |
| } else if (HTTPStatusCodeFamily.SUCCESSFUL.equals(family)) { |
| // Save the HttpMethod so that we can release the connection when |
| // cleaning up |
| // TODO : Do we need to save the http method |
| // msgContext.setProperty(HTTPConstants.HTTP_METHOD, method); |
| processResponse(response, 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 = response.getFirstHeader(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(response, msgContext); |
| } |
| |
| if (org.apache.axis2.util.Utils.isClientThreadNonBlockingPropertySet(msgContext)) { |
| throw new AxisFault(Messages. |
| getMessage("transportError", |
| String.valueOf(statusCode), |
| response.getStatusLine().toString())); |
| } |
| } else { |
| throw new AxisFault(Messages.getMessage("transportError", String.valueOf(statusCode), |
| response.getStatusLine().toString())); |
| } |
| } |
| |
| /** |
| * Collect the HTTP header information and set them in the message context |
| * |
| * @param httpResponse which holds the header information |
| * @param msgContext the MessageContext in which to place the information... OR |
| * NOT! |
| * @throws AxisFault if problems occur |
| */ |
| protected void obtainHTTPHeaderInformation(Object httpResponse, MessageContext msgContext) |
| throws AxisFault { |
| HttpResponse response; |
| if (httpResponse instanceof HttpResponse) { |
| response = (HttpResponse) httpResponse; |
| } 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(response.getAllHeaders()); |
| msgContext.setProperty(MessageContext.TRANSPORT_HEADERS, transportHeaders); |
| msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, |
| new Integer(response.getStatusLine().getStatusCode())); |
| Header header = response.getFirstHeader(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 = response.getHeaders(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 = response.getHeaders(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(HttpResponse response, MessageContext msgContext) |
| throws IOException { |
| obtainHTTPHeaderInformation(response, msgContext); |
| |
| HttpEntity httpEntity = response.getEntity(); |
| InputStream in = httpEntity.getContent(); |
| if (in == null) { |
| throw new AxisFault(Messages.getMessage("canNotBeNull", "InputStream")); |
| } |
| Header contentEncoding = httpEntity.getContentEncoding(); |
| 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 org.apache.axis2.AxisFault if problems occur |
| */ |
| protected HttpHost getHostConfiguration(AbstractHttpClient 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 |
| HttpHost hostConfig = new HttpHost(targetURL.getHost(), port, targetURL.getProtocol()); |
| |
| // TODO : one might need to set his own socket factory. We have to allow that case as well. |
| |
| if (isAuthenticationEnabled) { |
| // Basic, Digest, NTLM and custom authentications. |
| this.setAuthenticationInfo(client, msgCtx); |
| } |
| // proxy configuration |
| |
| if (HTTPProxyConfigurator.isProxyEnabled(msgCtx, targetURL)) { |
| if (log.isDebugEnabled()) { |
| log.debug("Configuring HTTP proxy."); |
| } |
| HTTPProxyConfigurator.configure(msgCtx, client); |
| } |
| |
| return hostConfig; |
| } |
| |
| 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(AbstractHttpClient agent, MessageContext msgCtx) |
| 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; |
| |
| // TODO : Set preemptive authentication, but its not recommended in HC 4 |
| |
| if (host != null) { |
| if (domain != null) { |
| /* Credentials for NTLM Authentication */ |
| //TODO : To enable NTLM we have to register the scheme with client, but it is available from 4.1 only |
| // agent.getAuthSchemes().register("ntlm",new NTLMSchemeFactory()); |
| creds = new NTCredentials(username, password, host, domain); |
| } else { |
| /* Credentials for Digest and Basic Authentication */ |
| creds = new UsernamePasswordCredentials(username, password); |
| } |
| agent.getCredentialsProvider(). |
| setCredentials(new AuthScope(host, port, realm), creds); |
| } else { |
| if (domain != null) { |
| /* |
| * Credentials for NTLM Authentication when host is |
| * ANY_HOST |
| */ |
| // TODO : Enable NTLM as metioned above |
| creds = new NTCredentials(username, password, AuthScope.ANY_HOST, domain); |
| agent.getCredentialsProvider(). |
| setCredentials(new AuthScope(AuthScope.ANY_HOST, port, realm), |
| creds); |
| } else { |
| /* Credentials only for Digest and Basic Authentication */ |
| creds = new UsernamePasswordCredentials(username, password); |
| agent.getCredentialsProvider(). |
| 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)); |
| |
| } |
| // TODO : This is available in 4.1 only |
| // agent.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, 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 org.apache.axis2.AxisFault - Thrown in case an exception occurs |
| */ |
| protected MessageFormatter populateCommonProperties(MessageContext msgContext, URL url, |
| HttpRequestBase httpMethod, |
| AbstractHttpClient httpClient, |
| String soapActionString) |
| throws AxisFault { |
| |
| if (isAuthenticationEnabled(msgContext)) { |
| httpMethod.getParams().setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, true); |
| } |
| |
| MessageFormatter messageFormatter = TransportUtils.getMessageFormatter(msgContext); |
| |
| url = messageFormatter.getTargetAddress(msgContext, format, url); |
| |
| try { |
| httpMethod.setURI(url.toURI()); |
| } catch (URISyntaxException e) { |
| log.error("Error in URI : " + url, e); |
| } |
| |
| httpMethod.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, |
| messageFormatter.getContentType(msgContext, format, soapActionString)); |
| |
| httpMethod.setHeader(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.setHeader(HTTPConstants.HEADER_COOKIE, buffer.toString()); |
| } |
| } |
| |
| if (httpVersion.equals(HTTPConstants.HEADER_PROTOCOL_10)) { |
| httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, |
| 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, AbstractHttpClient 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.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, |
| connectionTimeout); |
| } else { |
| // set timeout in client |
| if (timeout > 0) { |
| httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, |
| (int) timeout); |
| } |
| } |
| |
| if (tempSoTimeoutProperty != null) { |
| int soTimeout = tempSoTimeoutProperty.intValue(); |
| // SO_TIMEOUT -- timeout for blocking reads |
| httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeout); |
| } else { |
| // set timeout in client |
| if (timeout > 0) { |
| httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, (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, HttpRequestBase 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(CoreConnectionPNames.CONNECTION_TIMEOUT, |
| tempConnTimeoutProperty); |
| } |
| |
| if (tempSoTimeoutProperty != null) { |
| // SO_TIMEOUT -- timeout for blocking reads |
| httpMethod.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, |
| tempSoTimeoutProperty); |
| } else { |
| // set timeout in client |
| if (timeout > 0) { |
| httpMethod.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, (int) timeout); |
| } |
| } |
| } |
| |
| protected AbstractHttpClient getHttpClient(MessageContext msgContext) { |
| ConfigurationContext configContext = msgContext.getConfigurationContext(); |
| |
| AbstractHttpClient httpClient = (AbstractHttpClient) msgContext |
| .getProperty(HTTPConstants.CACHED_HTTP_CLIENT); |
| |
| if (httpClient == null) { |
| httpClient = (AbstractHttpClient) configContext. |
| getProperty(HTTPConstants.CACHED_HTTP_CLIENT); |
| } |
| |
| if (httpClient != null) { |
| return httpClient; |
| } |
| |
| synchronized (this) { |
| httpClient = (AbstractHttpClient) msgContext. |
| getProperty(HTTPConstants.CACHED_HTTP_CLIENT); |
| |
| if (httpClient == null) { |
| httpClient = (AbstractHttpClient) configContext |
| .getProperty(HTTPConstants.CACHED_HTTP_CLIENT); |
| } |
| |
| if (httpClient != null) { |
| return httpClient; |
| } |
| |
| ClientConnectionManager connManager = (ClientConnectionManager) msgContext |
| .getProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER); |
| if (connManager == null) { |
| connManager = (ClientConnectionManager) msgContext |
| .getProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER); |
| } |
| if (connManager == null) { |
| // reuse HttpConnectionManager |
| synchronized (configContext) { |
| connManager = (ClientConnectionManager) configContext |
| .getProperty(HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER); |
| if (connManager == null) { |
| log.trace("Making new ConnectionManager"); |
| SchemeRegistry schemeRegistry = new SchemeRegistry(); |
| schemeRegistry.register( |
| new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); |
| schemeRegistry.register( |
| new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); |
| |
| HttpParams params = new BasicHttpParams(); |
| params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30); |
| params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, |
| new ConnPerRouteBean(30)); |
| connManager = new ThreadSafeClientConnManager(params, |
| schemeRegistry); |
| 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. |
| */ |
| HttpParams clientParams = new BasicHttpParams(); |
| clientParams.setParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET, "UTF-8"); |
| httpClient = new DefaultHttpClient(connManager, clientParams); |
| |
| //We don't need to set timeout for connection manager, since we are doing it below |
| // and its enough |
| |
| // Get the timeout values set in the runtime |
| initializeTimeouts(msgContext, httpClient); |
| |
| return httpClient; |
| } |
| } |
| |
| protected HttpResponse executeMethod(AbstractHttpClient httpClient, MessageContext msgContext, |
| URL url, |
| HttpRequestBase method) throws IOException { |
| HttpHost httpHost = 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.addHeader(HTTPConstants.HEADER_ACCEPT_ENCODING, |
| HTTPConstants.COMPRESSION_GZIP); |
| } |
| |
| if (msgContext.isPropertyTrue(HTTPConstants.MC_GZIP_REQUEST)) { |
| method.addHeader(HTTPConstants.HEADER_CONTENT_ENCODING, |
| HTTPConstants.COMPRESSION_GZIP); |
| } |
| |
| if (msgContext.getProperty(HTTPConstants.HTTP_METHOD_PARAMS) != null) { |
| HttpParams params = (HttpParams) msgContext |
| .getProperty(HTTPConstants.HTTP_METHOD_PARAMS); |
| method.setParams(params); |
| } |
| |
| String cookiePolicy = (String) msgContext.getProperty(HTTPConstants.COOKIE_POLICY); |
| if (cookiePolicy != null) { |
| method.getParams().setParameter(ClientPNames.COOKIE_POLICY, cookiePolicy); |
| } |
| |
| setTimeouts(msgContext, method); |
| HttpContext localContext = new BasicHttpContext(); |
| // Why do we have add context here |
| return httpClient.execute(httpHost, method, localContext); |
| } |
| |
| public void addCustomHeaders(HttpRequestBase 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 BasicHeader(nv.getName(), nv.getValue()); |
| if (HTTPConstants.HEADER_USER_AGENT.equals(header.getName())) { |
| isCustomUserAgentSet = true; |
| } |
| method.addHeader(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.addHeader(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.getAllHeaders(); |
| |
| boolean headerAdded = false; |
| for (Header header : headers) { |
| if (header.getName() != null |
| && header.getName().equals(((Map.Entry) headerEntry).getKey())) { |
| headerAdded = true; |
| break; |
| } |
| } |
| |
| if (!headerAdded) { |
| method.addHeader(((Map.Entry) headerEntry).getKey().toString(), |
| ((Map.Entry) headerEntry).getValue().toString()); |
| } |
| } |
| } |
| } |
| |
| if (!isCustomUserAgentSet) { |
| String userAgentString = getUserAgent(msgContext); |
| method.setHeader(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; |
| } |
| |
| } |