1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.transport.http;
18
19 import java.io.IOException;
20 import java.net.URI;
21 import java.net.URISyntaxException;
22 import java.util.Map;
23
24 import org.springframework.beans.factory.DisposableBean;
25 import org.springframework.beans.factory.InitializingBean;
26 import org.springframework.util.Assert;
27 import org.springframework.ws.transport.WebServiceConnection;
28
29 import org.apache.http.HttpEntityEnclosingRequest;
30 import org.apache.http.HttpException;
31 import org.apache.http.HttpHost;
32 import org.apache.http.HttpRequest;
33 import org.apache.http.HttpRequestInterceptor;
34 import org.apache.http.auth.AuthScope;
35 import org.apache.http.auth.Credentials;
36 import org.apache.http.auth.UsernamePasswordCredentials;
37 import org.apache.http.client.HttpClient;
38 import org.apache.http.client.methods.HttpPost;
39 import org.apache.http.conn.ClientConnectionManager;
40 import org.apache.http.conn.routing.HttpRoute;
41 import org.apache.http.impl.client.DefaultHttpClient;
42 import org.apache.http.impl.conn.SingleClientConnManager;
43 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
44 import org.apache.http.params.HttpConnectionParams;
45 import org.apache.http.protocol.HTTP;
46 import org.apache.http.protocol.HttpContext;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class HttpComponentsMessageSender extends AbstractHttpWebServiceMessageSender
63 implements InitializingBean, DisposableBean {
64
65 private static final int DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS = (60 * 1000);
66
67 private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);
68
69 private HttpClient httpClient;
70
71 private Credentials credentials;
72
73 private AuthScope authScope = AuthScope.ANY;
74
75
76
77
78
79 public HttpComponentsMessageSender() {
80 DefaultHttpClient defaultClient = new DefaultHttpClient(new ThreadSafeClientConnManager());
81 defaultClient.addRequestInterceptor(new RemoveSoapHeadersInterceptor(), 0);
82
83 this.httpClient = defaultClient;
84 setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS);
85 setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
86 }
87
88
89
90
91
92
93 public HttpComponentsMessageSender(HttpClient httpClient) {
94 Assert.notNull(httpClient, "httpClient must not be null");
95 this.httpClient = httpClient;
96 }
97
98
99
100
101
102
103
104 public void setCredentials(Credentials credentials) {
105 this.credentials = credentials;
106 }
107
108
109
110
111 public HttpClient getHttpClient() {
112 return httpClient;
113 }
114
115
116
117
118 public void setHttpClient(HttpClient httpClient) {
119 this.httpClient = httpClient;
120 }
121
122
123
124
125
126
127
128 public void setConnectionTimeout(int timeout) {
129 if (timeout < 0) {
130 throw new IllegalArgumentException("timeout must be a non-negative value");
131 }
132 HttpConnectionParams.setConnectionTimeout(getHttpClient().getParams(), timeout);
133 }
134
135
136
137
138
139
140
141 public void setReadTimeout(int timeout) {
142 if (timeout < 0) {
143 throw new IllegalArgumentException("timeout must be a non-negative value");
144 }
145 HttpConnectionParams.setSoTimeout(getHttpClient().getParams(), timeout);
146 }
147
148
149
150
151
152
153
154 public void setMaxTotalConnections(int maxTotalConnections) {
155 if (maxTotalConnections <= 0) {
156 throw new IllegalArgumentException("maxTotalConnections must be a positive value");
157 }
158 ClientConnectionManager connectionManager = getHttpClient().getConnectionManager();
159 if (!(connectionManager instanceof ThreadSafeClientConnManager)) {
160 throw new IllegalArgumentException("maxTotalConnections is not supported on " +
161 connectionManager.getClass().getName() + ". Use " + ThreadSafeClientConnManager.class.getName() +
162 " instead");
163 }
164 ((ThreadSafeClientConnManager) connectionManager).setMaxTotal(maxTotalConnections);
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 public void setMaxConnectionsPerHost(Map<String, String> maxConnectionsPerHost) throws URISyntaxException {
184 ClientConnectionManager connectionManager = getHttpClient().getConnectionManager();
185 if (!(connectionManager instanceof ThreadSafeClientConnManager)) {
186 throw new IllegalArgumentException("maxConnectionsPerHost is not supported on " +
187 connectionManager.getClass().getName() + ". Use " + ThreadSafeClientConnManager.class.getName() +
188 " instead");
189 }
190
191 for (Object o : maxConnectionsPerHost.keySet()) {
192 String host = (String) o;
193 URI uri = new URI(host);
194 HttpHost httpHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
195 int maxHostConnections = Integer.parseInt(maxConnectionsPerHost.get(host));
196 ((ThreadSafeClientConnManager) connectionManager)
197 .setMaxForRoute(new HttpRoute(httpHost), maxHostConnections);
198 }
199 }
200
201
202
203
204
205
206
207
208 public void setAuthScope(AuthScope authScope) {
209 this.authScope = authScope;
210 }
211
212 public void afterPropertiesSet() throws Exception {
213 if (credentials != null && getHttpClient() instanceof DefaultHttpClient) {
214 ((DefaultHttpClient) getHttpClient()).getCredentialsProvider().setCredentials(authScope, credentials);
215 }
216 }
217
218 public WebServiceConnection createConnection(URI uri) throws IOException {
219 HttpPost httpPost = new HttpPost(uri);
220 if (isAcceptGzipEncoding()) {
221 httpPost.addHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
222 HttpTransportConstants.CONTENT_ENCODING_GZIP);
223 }
224 HttpContext httpContext = createContext(uri);
225 return new HttpComponentsConnection(getHttpClient(), httpPost, httpContext);
226 }
227
228
229
230
231
232
233
234
235 protected HttpContext createContext(URI uri) {
236 return null;
237 }
238
239 public void destroy() throws Exception {
240 getHttpClient().getConnectionManager().shutdown();
241 }
242
243
244
245
246
247
248 private static class RemoveSoapHeadersInterceptor implements HttpRequestInterceptor {
249
250 public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
251 if (request instanceof HttpEntityEnclosingRequest) {
252 if (request.containsHeader(HTTP.TRANSFER_ENCODING)) {
253 request.removeHeaders(HTTP.TRANSFER_ENCODING);
254 }
255 if (request.containsHeader(HTTP.CONTENT_LEN)) {
256 request.removeHeaders(HTTP.CONTENT_LEN);
257 }
258 }
259 }
260 }
261 }