1
2
3
4
5
6
7 package org.mule.transport.http;
8
9 import org.mule.api.MuleContext;
10 import org.mule.api.MuleEvent;
11 import org.mule.api.MuleMessage;
12 import org.mule.api.construct.FlowConstruct;
13 import org.mule.api.endpoint.ImmutableEndpoint;
14 import org.mule.api.endpoint.InboundEndpoint;
15 import org.mule.api.lifecycle.InitialisationException;
16 import org.mule.api.processor.MessageProcessor;
17 import org.mule.config.i18n.CoreMessages;
18 import org.mule.transport.http.ntlm.NTLMScheme;
19 import org.mule.transport.tcp.TcpConnector;
20
21 import java.io.UnsupportedEncodingException;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.apache.commons.codec.binary.Base64;
29 import org.apache.commons.httpclient.Credentials;
30 import org.apache.commons.httpclient.HttpClient;
31 import org.apache.commons.httpclient.HttpConnectionManager;
32 import org.apache.commons.httpclient.HttpMethod;
33 import org.apache.commons.httpclient.HttpState;
34 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
35 import org.apache.commons.httpclient.NTCredentials;
36 import org.apache.commons.httpclient.UsernamePasswordCredentials;
37 import org.apache.commons.httpclient.auth.AuthPolicy;
38 import org.apache.commons.httpclient.auth.AuthScope;
39 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
40 import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class HttpConnector extends TcpConnector
61 {
62
63 public static final String HTTP = "http";
64 public static final String HTTP_PREFIX = "http.";
65
66
67
68
69 public static final String HTTP_STATUS_PROPERTY = HTTP_PREFIX + "status";
70 public static final String HTTP_VERSION_PROPERTY = HTTP_PREFIX + "version";
71
72
73
74
75 @Deprecated
76 public static final String HTTP_CUSTOM_HEADERS_MAP_PROPERTY = HTTP_PREFIX + "custom.headers";
77
78 public static final String HTTP_METHOD_PROPERTY = HTTP_PREFIX + "method";
79
80
81
82
83 public static final String HTTP_REQUEST_PROPERTY = HTTP_PREFIX + "request";
84
85
86
87
88 public static final String HTTP_REQUEST_PATH_PROPERTY = HTTP_PREFIX + "request.path";
89
90
91
92
93
94 public static final String HTTP_CONTEXT_PATH_PROPERTY = HTTP_PREFIX + "context.path";
95
96
97
98
99
100 public static final String HTTP_PARAMS_PROPERTY = HTTP_PREFIX + "params";
101 public static final String HTTP_GET_BODY_PARAM_PROPERTY = HTTP_PREFIX + "get.body.param";
102 public static final String DEFAULT_HTTP_GET_BODY_PARAM_PROPERTY = "body";
103 public static final String HTTP_POST_BODY_PARAM_PROPERTY = HTTP_PREFIX + "post.body.param";
104
105 public static final String HTTP_DISABLE_STATUS_CODE_EXCEPTION_CHECK = HTTP_PREFIX + "disable.status.code.exception.check";
106 public static final String HTTP_ENCODE_PARAMVALUE = HTTP_PREFIX + "encode.paramvalue";
107
108 public static final Set<String> HTTP_INBOUND_PROPERTIES;
109
110 static
111 {
112 Set<String> props = new HashSet<String>();
113 props.add(HTTP_CONTEXT_PATH_PROPERTY);
114 props.add(HTTP_GET_BODY_PARAM_PROPERTY);
115 props.add(HTTP_METHOD_PROPERTY);
116 props.add(HTTP_PARAMS_PROPERTY);
117 props.add(HTTP_POST_BODY_PARAM_PROPERTY);
118 props.add(HTTP_REQUEST_PROPERTY);
119 props.add(HTTP_REQUEST_PATH_PROPERTY);
120 props.add(HTTP_STATUS_PROPERTY);
121 props.add(HTTP_VERSION_PROPERTY);
122 props.add(HTTP_ENCODE_PARAMVALUE);
123 HTTP_INBOUND_PROPERTIES = props;
124
125 AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, NTLMScheme.class);
126 }
127
128 public static final String HTTP_COOKIE_SPEC_PROPERTY = "cookieSpec";
129 public static final String HTTP_COOKIES_PROPERTY = "cookies";
130 public static final String HTTP_ENABLE_COOKIES_PROPERTY = "enableCookies";
131
132 public static final String COOKIE_SPEC_NETSCAPE = "netscape";
133 public static final String COOKIE_SPEC_RFC2109 = "rfc2109";
134
135 private String proxyHostname = null;
136
137 private int proxyPort = HttpConstants.DEFAULT_HTTP_PORT;
138
139 private String proxyUsername = null;
140
141 private String proxyPassword = null;
142
143 private boolean proxyNtlmAuthentication;
144
145 private String cookieSpec;
146
147 private boolean enableCookies = false;
148
149 protected HttpConnectionManager clientConnectionManager;
150
151 private IdleConnectionTimeoutThread connectionCleaner;
152
153 private boolean disableCleanupThread;
154
155 public HttpConnector(MuleContext context)
156 {
157 super(context);
158 }
159
160 @Override
161 protected void doInitialise() throws InitialisationException
162 {
163 super.doInitialise();
164 if (clientConnectionManager == null)
165 {
166 clientConnectionManager = new MultiThreadedHttpConnectionManager();
167 String prop = System.getProperty("mule.http.disableCleanupThread");
168 disableCleanupThread = prop != null && prop.equals("true");
169 if (!disableCleanupThread)
170 {
171 connectionCleaner = new IdleConnectionTimeoutThread();
172 connectionCleaner.setName("HttpClient-connection-cleaner-" + getName());
173 connectionCleaner.addConnectionManager(clientConnectionManager);
174 connectionCleaner.start();
175 }
176
177 HttpConnectionManagerParams params = new HttpConnectionManagerParams();
178 if (getSendBufferSize() != INT_VALUE_NOT_SET)
179 {
180 params.setSendBufferSize(getSendBufferSize());
181 }
182 if (getReceiveBufferSize() != INT_VALUE_NOT_SET)
183 {
184 params.setReceiveBufferSize(getReceiveBufferSize());
185 }
186 if (getClientSoTimeout() != INT_VALUE_NOT_SET)
187 {
188 params.setSoTimeout(getClientSoTimeout());
189 }
190 if (getSocketSoLinger() != INT_VALUE_NOT_SET)
191 {
192 params.setLinger(getSocketSoLinger());
193 }
194
195 params.setTcpNoDelay(isSendTcpNoDelay());
196 params.setMaxTotalConnections(dispatchers.getMaxTotal());
197 params.setDefaultMaxConnectionsPerHost(dispatchers.getMaxTotal());
198 clientConnectionManager.setParams(params);
199 }
200 }
201
202 @Override
203 protected void doDispose()
204 {
205 if (!disableCleanupThread)
206 {
207 connectionCleaner.shutdown();
208
209 if (!muleContext.getConfiguration().isStandalone())
210 {
211 MultiThreadedHttpConnectionManager.shutdownAll();
212 }
213 }
214 super.doDispose();
215 }
216
217 @Override
218 public void registerListener(InboundEndpoint endpoint, MessageProcessor listener, FlowConstruct flowConstruct) throws Exception
219 {
220 if (endpoint != null)
221 {
222 Map endpointProperties = endpoint.getProperties();
223 if (endpointProperties != null)
224 {
225
226 Map newProperties = new HashMap(endpointProperties.size());
227 for (Iterator entries = endpointProperties.entrySet().iterator(); entries.hasNext();)
228 {
229 Map.Entry entry = (Map.Entry) entries.next();
230 Object key = entry.getKey();
231 Object normalizedKey = HttpConstants.ALL_HEADER_NAMES.get(key);
232 if (normalizedKey != null)
233 {
234
235 key = normalizedKey;
236 }
237 newProperties.put(key, entry.getValue());
238 }
239
240 endpoint.getProperties().clear();
241 endpoint.getProperties().putAll(newProperties);
242 }
243 }
244
245 super.registerListener(endpoint, listener, flowConstruct);
246 }
247
248
249
250
251
252
253
254 @Override
255 protected Object getReceiverKey(FlowConstruct flowConstruct, InboundEndpoint endpoint)
256 {
257 String key = endpoint.getEndpointURI().toString();
258 int i = key.indexOf('?');
259 if (i > -1)
260 {
261 key = key.substring(0, i);
262 }
263 return key;
264 }
265
266
267
268
269 @Override
270 public String getProtocol()
271 {
272 return HTTP;
273 }
274
275 public String getProxyHostname()
276 {
277 return proxyHostname;
278 }
279
280 public String getProxyPassword()
281 {
282 return proxyPassword;
283 }
284
285 public int getProxyPort()
286 {
287 return proxyPort;
288 }
289
290 public String getProxyUsername()
291 {
292 return proxyUsername;
293 }
294
295 public void setProxyHostname(String host)
296 {
297 proxyHostname = host;
298 }
299
300 public void setProxyPassword(String string)
301 {
302 proxyPassword = string;
303 }
304
305 public void setProxyPort(int port)
306 {
307 proxyPort = port;
308 }
309
310 public void setProxyUsername(String string)
311 {
312 proxyUsername = string;
313 }
314
315 @Override
316 public Map getReceivers()
317 {
318 return this.receivers;
319 }
320
321 public String getCookieSpec()
322 {
323 return cookieSpec;
324 }
325
326 public void setCookieSpec(String cookieSpec)
327 {
328 if (!(COOKIE_SPEC_NETSCAPE.equalsIgnoreCase(cookieSpec) || COOKIE_SPEC_RFC2109.equalsIgnoreCase(cookieSpec)))
329 {
330 throw new IllegalArgumentException(
331 CoreMessages.propertyHasInvalidValue("cookieSpec", cookieSpec).toString());
332 }
333 this.cookieSpec = cookieSpec;
334 }
335
336 public boolean isEnableCookies()
337 {
338 return enableCookies;
339 }
340
341 public void setEnableCookies(boolean enableCookies)
342 {
343 this.enableCookies = enableCookies;
344 }
345
346
347 public HttpConnectionManager getClientConnectionManager()
348 {
349 return clientConnectionManager;
350 }
351
352 public void setClientConnectionManager(HttpConnectionManager clientConnectionManager)
353 {
354 this.clientConnectionManager = clientConnectionManager;
355 }
356
357 protected HttpClient doClientConnect() throws Exception
358 {
359 HttpState state = new HttpState();
360
361 if (getProxyUsername() != null)
362 {
363 Credentials credentials;
364 if (isProxyNtlmAuthentication())
365 {
366 credentials = new NTCredentials(getProxyUsername(), getProxyPassword(), getProxyHostname(), "");
367 }
368 else
369 {
370 credentials = new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword());
371 }
372
373 AuthScope authscope = new AuthScope(getProxyHostname(), getProxyPort());
374
375 state.setProxyCredentials(authscope, credentials);
376 }
377
378 HttpClient client = new HttpClient();
379 client.setState(state);
380 client.setHttpConnectionManager(getClientConnectionManager());
381
382 return client;
383 }
384
385 protected void setupClientAuthorization(MuleEvent event, HttpMethod httpMethod,
386 HttpClient client, ImmutableEndpoint endpoint)
387 throws UnsupportedEncodingException
388 {
389 httpMethod.setDoAuthentication(true);
390 client.getParams().setAuthenticationPreemptive(true);
391
392 if (event != null && event.getCredentials() != null)
393 {
394 MuleMessage msg = event.getMessage();
395 String authScopeHost = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.host", event.getEndpoint().getEndpointURI().getHost());
396 int authScopePort = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.port", event.getEndpoint().getEndpointURI().getPort());
397 String authScopeRealm = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.realm", AuthScope.ANY_REALM);
398 String authScopeScheme = msg.getOutboundProperty(HTTP_PREFIX + "auth.scope.scheme", AuthScope.ANY_SCHEME);
399 client.getState().setCredentials(
400 new AuthScope(authScopeHost, authScopePort, authScopeRealm, authScopeScheme),
401 new UsernamePasswordCredentials(event.getCredentials().getUsername(), new String(
402 event.getCredentials().getPassword())));
403 }
404 else if (endpoint.getEndpointURI().getUserInfo() != null
405 && endpoint.getProperty(HttpConstants.HEADER_AUTHORIZATION) == null)
406 {
407
408 StringBuffer header = new StringBuffer(128);
409 header.append("Basic ");
410 header.append(new String(Base64.encodeBase64(endpoint.getEndpointURI().getUserInfo().getBytes(
411 endpoint.getEncoding()))));
412 httpMethod.addRequestHeader(HttpConstants.HEADER_AUTHORIZATION, header.toString());
413 }
414
415 else if (event!=null && event.getMessage().getOutboundProperty(HttpConstants.HEADER_AUTHORIZATION) != null &&
416 httpMethod.getRequestHeader(HttpConstants.HEADER_AUTHORIZATION)==null)
417 {
418 String auth = event.getMessage().getOutboundProperty(HttpConstants.HEADER_AUTHORIZATION);
419 httpMethod.addRequestHeader(HttpConstants.HEADER_AUTHORIZATION, auth);
420 }
421 else
422 {
423
424 client.getParams().setAuthenticationPreemptive(false);
425 }
426 }
427
428
429
430
431 public static String normalizeUrl(String url)
432 {
433 if (url == null)
434 {
435 url = "/";
436 }
437 else if (!url.startsWith("/"))
438 {
439 url = "/" + url;
440 }
441 return url;
442 }
443
444 public boolean isProxyNtlmAuthentication()
445 {
446 return proxyNtlmAuthentication;
447 }
448
449 public void setProxyNtlmAuthentication(boolean proxyNtlmAuthentication)
450 {
451 this.proxyNtlmAuthentication = proxyNtlmAuthentication;
452 }
453 }