View Javadoc

1   /*
2    * Copyright 2005-2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.transport.http;
18  
19  import java.io.IOException;
20  import java.net.URI;
21  import java.util.Map;
22  
23  import org.springframework.beans.factory.DisposableBean;
24  import org.springframework.beans.factory.InitializingBean;
25  import org.springframework.util.Assert;
26  import org.springframework.ws.transport.WebServiceConnection;
27  
28  import org.apache.commons.httpclient.Credentials;
29  import org.apache.commons.httpclient.HostConfiguration;
30  import org.apache.commons.httpclient.HttpClient;
31  import org.apache.commons.httpclient.HttpConnectionManager;
32  import org.apache.commons.httpclient.HttpURL;
33  import org.apache.commons.httpclient.HttpsURL;
34  import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
35  import org.apache.commons.httpclient.NTCredentials;
36  import org.apache.commons.httpclient.URIException;
37  import org.apache.commons.httpclient.UsernamePasswordCredentials;
38  import org.apache.commons.httpclient.auth.AuthScope;
39  import org.apache.commons.httpclient.methods.PostMethod;
40  
41  /**
42   * <code>WebServiceMessageSender</code> implementation that uses <a href="http://jakarta.apache.org/commons/httpclient">Jakarta
43   * Commons HttpClient</a> to execute POST requests.
44   * <p/>
45   * Allows to use a preconfigured HttpClient instance, potentially with authentication, HTTP connection pooling, etc.
46   * Authentication can also be set by injecting a {@link Credentials} instance (such as the {@link
47   * UsernamePasswordCredentials}).
48   *
49   * @author Arjen Poutsma
50   * @see HttpUrlConnectionMessageSender
51   * @see HttpClient
52   * @see #setCredentials(Credentials)
53   * @since 1.0.0
54   * @deprecated In favor of {@link HttpComponentsMessageSender}
55   */
56  @Deprecated
57  public class CommonsHttpMessageSender extends AbstractHttpWebServiceMessageSender
58          implements InitializingBean, DisposableBean {
59  
60      private static final int DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS = (60 * 1000);
61  
62      private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);
63  
64      private HttpClient httpClient;
65  
66      private Credentials credentials;
67  
68      private AuthScope authScope;
69  
70      /**
71       * Create a new instance of the <code>CommonsHttpMessageSender</code> with a default {@link HttpClient} that uses a
72       * default {@link MultiThreadedHttpConnectionManager}.
73       */
74      public CommonsHttpMessageSender() {
75          httpClient = new HttpClient(new MultiThreadedHttpConnectionManager());
76          setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS);
77          setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
78      }
79  
80      /**
81       * Create a new instance of the <code>CommonsHttpMessageSender</code> with the given  {@link HttpClient} instance.
82       *
83       * @param httpClient the HttpClient instance to use for this sender
84       */
85      public CommonsHttpMessageSender(HttpClient httpClient) {
86          Assert.notNull(httpClient, "httpClient must not be null");
87          this.httpClient = httpClient;
88      }
89  
90      /** Returns the <code>HttpClient</code> used by this message sender. */
91      public HttpClient getHttpClient() {
92          return httpClient;
93      }
94  
95      /** Set the <code>HttpClient</code> used by this message sender. */
96      public void setHttpClient(HttpClient httpClient) {
97          this.httpClient = httpClient;
98      }
99  
100     /** Returns the credentials to be used. */
101     public Credentials getCredentials() {
102         return credentials;
103     }
104 
105     /**
106      * Sets the credentials to be used. If not set, no authentication is done.
107      *
108      * @see UsernamePasswordCredentials
109      * @see NTCredentials
110      */
111     public void setCredentials(Credentials credentials) {
112         this.credentials = credentials;
113     }
114 
115     /**
116      * Sets the timeout until a connection is etablished. A value of 0 means <em>never</em> timeout.
117      *
118      * @param timeout the timeout value in milliseconds
119      * @see org.apache.commons.httpclient.params.HttpConnectionManagerParams#setConnectionTimeout(int)
120      */
121     public void setConnectionTimeout(int timeout) {
122         if (timeout < 0) {
123             throw new IllegalArgumentException("timeout must be a non-negative value");
124         }
125         getHttpClient().getHttpConnectionManager().getParams().setConnectionTimeout(timeout);
126     }
127 
128     /**
129      * Set the socket read timeout for the underlying HttpClient. A value of 0 means <em>never</em> timeout.
130      *
131      * @param timeout the timeout value in milliseconds
132      * @see org.apache.commons.httpclient.params.HttpConnectionManagerParams#setSoTimeout(int)
133      */
134     public void setReadTimeout(int timeout) {
135         if (timeout < 0) {
136             throw new IllegalArgumentException("timeout must be a non-negative value");
137         }
138         getHttpClient().getHttpConnectionManager().getParams().setSoTimeout(timeout);
139     }
140 
141     /**
142      * Sets the maximum number of connections allowed for the underlying HttpClient.
143      *
144      * @param maxTotalConnections the maximum number of connections allowed
145      * @see org.apache.commons.httpclient.params.HttpConnectionManagerParams#setMaxTotalConnections(int)
146      */
147     public void setMaxTotalConnections(int maxTotalConnections) {
148         if (maxTotalConnections <= 0) {
149             throw new IllegalArgumentException("maxTotalConnections must be a positive value");
150         }
151         getHttpClient().getHttpConnectionManager().getParams().setMaxTotalConnections(maxTotalConnections);
152     }
153 
154     /**
155      * Sets the maximum number of connections per host for the underlying HttpClient. The maximum number of connections
156      * per host can be set in a form accepted by the {@code java.util.Properties} class, like as follows:
157      * <pre>
158      * https://www.example.com=1
159      * http://www.example.com:8080=7
160      * www.springframework.org=10
161      * *=5
162      * </pre>
163      * The host can be specified as hostname, or as URI (with scheme and port). The special host name {@code *} can be
164      * used to specify {@link org.apache.commons.httpclient.HostConfiguration#ANY_HOST_CONFIGURATION}.
165      *
166      * @param maxConnectionsPerHost a properties object specifying the maximum number of connection
167      * @see org.apache.commons.httpclient.params.HttpConnectionManagerParams#setMaxConnectionsPerHost(org.apache.commons.httpclient.HostConfiguration,
168      *      int)
169      */
170     public void setMaxConnectionsPerHost(Map<String, String> maxConnectionsPerHost) throws URIException {
171         for (String host : maxConnectionsPerHost.keySet()) {
172             HostConfiguration hostConfiguration = new HostConfiguration();
173             if ("*".equals(host)) {
174                 hostConfiguration = HostConfiguration.ANY_HOST_CONFIGURATION;
175             }
176             else if (host.startsWith("http://")) {
177                 HttpURL httpURL = new HttpURL(host);
178                 hostConfiguration.setHost(httpURL);
179             }
180             else if (host.startsWith("https://")) {
181                 HttpsURL httpsURL = new HttpsURL(host);
182                 hostConfiguration.setHost(httpsURL);
183             }
184             else {
185                 hostConfiguration.setHost(host);
186             }
187             int maxHostConnections = Integer.parseInt(maxConnectionsPerHost.get(host));
188             getHttpClient().getHttpConnectionManager().getParams()
189                     .setMaxConnectionsPerHost(hostConfiguration, maxHostConnections);
190         }
191     }
192 
193     /**
194      * Returns the authentication scope to be used. Only used when the <code>credentials</code> property has been set.
195      * <p/>
196      * By default, the {@link AuthScope#ANY} is returned.
197      */
198     public AuthScope getAuthScope() {
199         return authScope != null ? authScope : AuthScope.ANY;
200     }
201 
202     /**
203      * Sets the authentication scope to be used. Only used when the <code>credentials</code> property has been set.
204      * <p/>
205      * By default, the {@link AuthScope#ANY} is used.
206      *
207      * @see #setCredentials(Credentials)
208      */
209     public void setAuthScope(AuthScope authScope) {
210         this.authScope = authScope;
211     }
212 
213     public void afterPropertiesSet() throws Exception {
214         if (getCredentials() != null) {
215             getHttpClient().getState().setCredentials(getAuthScope(), getCredentials());
216             getHttpClient().getParams().setAuthenticationPreemptive(true);
217         }
218     }
219 
220     public void destroy() throws Exception {
221         HttpConnectionManager connectionManager = getHttpClient().getHttpConnectionManager();
222         if (connectionManager instanceof MultiThreadedHttpConnectionManager) {
223             ((MultiThreadedHttpConnectionManager) connectionManager).shutdown();
224         }
225     }
226 
227     public WebServiceConnection createConnection(URI uri) throws IOException {
228         PostMethod postMethod = new PostMethod(uri.toString());
229         if (isAcceptGzipEncoding()) {
230             postMethod.addRequestHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
231                     HttpTransportConstants.CONTENT_ENCODING_GZIP);
232         }
233         return new CommonsHttpConnection(getHttpClient(), postMethod);
234     }
235 
236 }
237