1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient;
31
32 import java.io.IOException;
33 import java.security.Provider;
34 import java.security.Security;
35
36 import org.apache.commons.httpclient.params.HttpClientParams;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39
40 /***
41 * <p>
42 * An HTTP "user-agent", containing an {@link HttpState HTTP state} and
43 * one or more {@link HttpConnection HTTP connections}, to which
44 * {@link HttpMethod HTTP methods} can be applied.
45 * </p>
46 * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
47 * @author <a href="mailto:rwaldhoff@apache.org">Rodney Waldhoff</a>
48 * @author Sean C. Sullivan
49 * @author <a href="mailto:dion@apache.org">dIon Gillard</a>
50 * @author Ortwin Gl?ck
51 * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
52 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
53 * @author Sam Maloney
54 * @author Laura Werner
55 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
56 *
57 * @version $Revision: 1.95 $ $Date: 2004/05/13 04:03:25 $
58 */
59 public class HttpClient {
60
61
62
63
64 /*** Log object for this class. */
65 private static final Log LOG = LogFactory.getLog(HttpClient.class);
66
67 static {
68
69 if (LOG.isDebugEnabled()) {
70 try {
71 LOG.debug("Java version: " + System.getProperty("java.version"));
72 LOG.debug("Java vendor: " + System.getProperty("java.vendor"));
73 LOG.debug("Java class path: " + System.getProperty("java.class.path"));
74 LOG.debug("Operating system name: " + System.getProperty("os.name"));
75 LOG.debug("Operating system architecture: " + System.getProperty("os.arch"));
76 LOG.debug("Operating system version: " + System.getProperty("os.version"));
77
78 Provider[] providers = Security.getProviders();
79 for (int i = 0; i < providers.length; i++) {
80 Provider provider = providers[i];
81 LOG.debug(provider.getName() + " " + provider.getVersion()
82 + ": " + provider.getInfo());
83 }
84 } catch (SecurityException ignore) {
85 }
86 }
87 }
88
89
90 /***
91 * Creates an instance of HttpClient using default {@link HttpClientParams parameter set}.
92 *
93 * @see HttpClientParams
94 */
95 public HttpClient() {
96 this(new HttpClientParams());
97 }
98
99 /***
100 * Creates an instance of HttpClient using the given
101 * {@link HttpClientParams parameter set}.
102 *
103 * @param params The {@link HttpClientParams parameters} to use.
104 *
105 * @see HttpClientParams
106 *
107 * @since 3.0
108 */
109 public HttpClient(HttpClientParams params) {
110 super();
111 if (params == null) {
112 throw new IllegalArgumentException("Params may not be null");
113 }
114 this.params = params;
115 this.httpConnectionManager = null;
116 Class clazz = params.getConnectionManagerClass();
117 if (clazz != null) {
118 try {
119 this.httpConnectionManager = (HttpConnectionManager) clazz.newInstance();
120 } catch (Exception e) {
121 LOG.warn("Error instantiating connection manager class, defaulting to"
122 + " SimpleHttpConnectionManager",
123 e);
124 }
125 }
126 if (this.httpConnectionManager == null) {
127 this.httpConnectionManager = new SimpleHttpConnectionManager();
128 }
129 if (this.httpConnectionManager != null) {
130 this.httpConnectionManager.getParams().setDefaults(this.params);
131 }
132 }
133
134 /***
135 * Creates an instance of HttpClient with a user specified
136 * {@link HttpClientParams parameter set} and
137 * {@link HttpConnectionManager HTTP connection manager}.
138 *
139 * @param params The {@link HttpClientParams parameters} to use.
140 * @param httpConnectionManager The {@link HttpConnectionManager connection manager}
141 * to use.
142 *
143 * @since 3.0
144 */
145 public HttpClient(HttpClientParams params, HttpConnectionManager httpConnectionManager) {
146 super();
147 if (httpConnectionManager == null) {
148 throw new IllegalArgumentException("httpConnectionManager cannot be null");
149 }
150 if (params == null) {
151 throw new IllegalArgumentException("Params may not be null");
152 }
153 this.params = params;
154 this.httpConnectionManager = httpConnectionManager;
155 if (this.httpConnectionManager != null) {
156 this.httpConnectionManager.getParams().setDefaults(this.params);
157 }
158 }
159
160 /***
161 * Creates an instance of HttpClient with a user specified
162 * {@link HttpConnectionManager HTTP connection manager}.
163 *
164 * @param httpConnectionManager The {@link HttpConnectionManager connection manager}
165 * to use.
166 *
167 * @since 2.0
168 */
169 public HttpClient(HttpConnectionManager httpConnectionManager) {
170 this(new HttpClientParams(), httpConnectionManager);
171 }
172
173
174
175 /***
176 * The {@link HttpConnectionManager connection manager} being used to manage
177 * connections for this HttpClient
178 */
179 private HttpConnectionManager httpConnectionManager;
180
181 /***
182 * The {@link HttpState HTTP state} associated with this HttpClient.
183 */
184 private HttpState state = new HttpState();
185
186 /***
187 * The {@link HttpClientParams collection of parameters} associated with this HttpClient.
188 */
189 private HttpClientParams params = null;
190
191 /***
192 * The {@link HostConfiguration host configuration} associated with
193 * the HttpClient
194 */
195 private HostConfiguration hostConfiguration = new HostConfiguration();
196
197
198
199 /***
200 * Returns {@link HttpState HTTP state} associated with the HttpClient.
201 *
202 * @see #setState(HttpState)
203 * @return the shared client state
204 */
205 public synchronized HttpState getState() {
206 return state;
207 }
208
209 /***
210 * Assigns {@link HttpState HTTP state} for the HttpClient.
211 *
212 * @see #getState()
213 * @param state the new {@link HttpState HTTP state} for the client
214 */
215 public synchronized void setState(HttpState state) {
216 this.state = state;
217 }
218
219 /***
220 * Defines how strictly the method follows the HTTP protocol specification
221 * (see RFC 2616 and other relevant RFCs).
222 *
223 * In the strict mode the method precisely
224 * implements the requirements of the specification, whereas in non-strict mode
225 * it attempts to mimic the exact behaviour of commonly used HTTP agents,
226 * which many HTTP servers expect.
227 *
228 * @param strictMode <tt>true</tt> for strict mode, <tt>false</tt> otherwise
229 *
230 * @see #isStrictMode()
231 *
232 * @deprecated Use {@link HttpClientParams#setParameter(String, Object)}
233 * to exercise a more granular control over HTTP protocol strictness.
234 */
235 public synchronized void setStrictMode(boolean strictMode) {
236 if (strictMode) {
237 this.params.makeStrict();
238 } else {
239 this.params.makeLenient();
240 }
241 }
242
243 /***
244 * Returns the value of the strict mode flag.
245 *
246 * @return <tt>true</tt> if strict mode is enabled, <tt>false</tt> otherwise
247 *
248 * @see #setStrictMode(boolean)
249 *
250 * @deprecated Use
251 * {@link org.apache.commons.httpclient.params.HttpClientParams#getParameter(String)}
252 * to exercise a more granular control over HTTP protocol strictness.
253 */
254 public synchronized boolean isStrictMode() {
255 return false;
256 }
257
258 /***
259 * Sets the socket timeout (<tt>SO_TIMEOUT</tt>) in milliseconds which is the
260 * timeout for waiting for data. A timeout value of zero is interpreted as an
261 * infinite timeout.
262 *
263 * @param newTimeoutInMilliseconds Timeout in milliseconds
264 *
265 * @deprecated Use
266 * {@link org.apache.commons.httpclient.params.HttpConnectionManagerParams#setSoTimeout(int)},
267 * {@link HttpConnectionManager#getParams()}.
268 *
269 */
270 public synchronized void setTimeout(int newTimeoutInMilliseconds) {
271 this.httpConnectionManager.getParams().setSoTimeout(newTimeoutInMilliseconds);
272 }
273
274 /***
275 * Sets the timeout in milliseconds used when retrieving an
276 * {@link HttpConnection HTTP connection} from the
277 * {@link HttpConnectionManager HTTP connection manager}.
278 *
279 * @param timeout the timeout in milliseconds
280 *
281 * @see HttpConnectionManager#getConnection(HostConfiguration, long)
282 *
283 * @deprecated Use
284 * {@link org.apache.commons.httpclient.params.HttpClientParams#setConnectionManagerTimeout(long)},
285 * {@link HttpClient#getParams()}
286 */
287 public synchronized void setHttpConnectionFactoryTimeout(long timeout) {
288 this.params.setConnectionManagerTimeout(timeout);
289 }
290
291 /***
292 * Sets the timeout until a connection is etablished. A value of zero
293 * means the timeout is not used. The default value is zero.
294 *
295 * @see HttpConnection#setConnectionTimeout(int)
296 * @param newTimeoutInMilliseconds Timeout in milliseconds.
297 *
298 * @deprecated Use
299 * {@link org.apache.commons.httpclient.params.HttpConnectionManagerParams#setConnectionTimeout(int)},
300 * {@link HttpConnectionManager#getParams()}.
301 */
302 public synchronized void setConnectionTimeout(int newTimeoutInMilliseconds) {
303 this.httpConnectionManager.getParams().setConnectionTimeout(newTimeoutInMilliseconds);
304 }
305
306
307
308 /***
309 * Executes the given {@link HttpMethod HTTP method}.
310 *
311 * @param method the {@link HttpMethod HTTP method} to execute.
312 * @return the method's response code
313 *
314 * @throws IOException If an I/O (transport) error occurs. Some transport exceptions
315 * can be recovered from.
316 * @throws HttpException If a protocol exception occurs. Usually protocol exceptions
317 * cannot be recovered from.
318 */
319 public int executeMethod(HttpMethod method)
320 throws IOException, HttpException {
321
322 LOG.trace("enter HttpClient.executeMethod(HttpMethod)");
323
324 return executeMethod(
325 method.getHostConfiguration() != null
326 ? method.getHostConfiguration()
327 : getHostConfiguration(),
328 method,
329 null
330 );
331
332 }
333
334 /***
335 * Executes the given {@link HttpMethod HTTP method} using custom
336 * {@link HostConfiguration host configuration}.
337 *
338 * @param hostConfiguration The {@link HostConfiguration host configuration} to use.
339 * @param method the {@link HttpMethod HTTP method} to execute.
340 * @return the method's response code
341 *
342 * @throws IOException If an I/O (transport) error occurs. Some transport exceptions
343 * can be recovered from.
344 * @throws HttpException If a protocol exception occurs. Usually protocol exceptions
345 * cannot be recovered from.
346 * @since 2.0
347 */
348 public int executeMethod(HostConfiguration hostConfiguration, HttpMethod method)
349 throws IOException, HttpException {
350
351 LOG.trace("enter HttpClient.executeMethod(HostConfiguration,HttpMethod)");
352
353 return executeMethod(hostConfiguration, method, null);
354 }
355
356
357
358 /***
359 * Executes the given {@link HttpMethod HTTP method} using the given custom
360 * {@link HostConfiguration host configuration} with the given custom
361 * {@link HttpState HTTP state}.
362 *
363 * @param hostConfiguration The {@link HostConfiguration host configuration} to use.
364 * @param method the {@link HttpMethod HTTP method} to execute.
365 * @param state the {@link HttpState HTTP state} to use when executing the method.
366 * If <code>null</code>, the state returned by {@link #getState} will be used instead.
367 *
368 * @return the method's response code
369 *
370 * @throws IOException If an I/O (transport) error occurs. Some transport exceptions
371 * can be recovered from.
372 * @throws HttpException If a protocol exception occurs. Usually protocol exceptions
373 * cannot be recovered from.
374 * @since 2.0
375 */
376 public int executeMethod(HostConfiguration hostConfiguration,
377 HttpMethod method, HttpState state)
378 throws IOException, HttpException {
379
380 LOG.trace("enter HttpClient.executeMethod(HostConfiguration,HttpMethod,HttpState)");
381
382 if (method == null) {
383 throw new IllegalArgumentException("HttpMethod parameter may not be null");
384 }
385
386 if (hostConfiguration == null) {
387 hostConfiguration = (
388 method.getHostConfiguration() != null
389 ? method.getHostConfiguration()
390 : getHostConfiguration()
391 );
392 }
393
394 HostConfiguration defaultHostConfiguration = null;
395 synchronized (this) {
396 defaultHostConfiguration = getHostConfiguration();
397 }
398 HostConfiguration methodConfiguration = new HostConfiguration(hostConfiguration);
399 if (hostConfiguration != defaultHostConfiguration) {
400
401 if (!methodConfiguration.isHostSet()) {
402 methodConfiguration.setHost(
403 defaultHostConfiguration.getHost(),
404 defaultHostConfiguration.getVirtualHost(),
405 defaultHostConfiguration.getPort(),
406 defaultHostConfiguration.getProtocol()
407 );
408 }
409 if (!methodConfiguration.isProxySet()
410 && defaultHostConfiguration.isProxySet()) {
411
412 methodConfiguration.setProxy(
413 defaultHostConfiguration.getProxyHost(),
414 defaultHostConfiguration.getProxyPort()
415 );
416 }
417 if (methodConfiguration.getLocalAddress() == null
418 && defaultHostConfiguration.getLocalAddress() != null) {
419
420 methodConfiguration.setLocalAddress(defaultHostConfiguration.getLocalAddress());
421 }
422 }
423
424
425
426
427
428 HttpMethodDirector methodDirector = null;
429 synchronized (this) {
430 methodDirector = new HttpMethodDirector(
431 this.httpConnectionManager,
432 methodConfiguration,
433 this.params,
434 (state == null ? getState() : state));
435 defaultHostConfiguration = getHostConfiguration();
436 }
437 methodDirector.executeMethod(method);
438 return method.getStatusCode();
439 }
440
441 /***
442 * Returns the default host.
443 *
444 * @return The default host.
445 *
446 * @deprecated use #getHostConfiguration()
447 */
448 public String getHost() {
449 return hostConfiguration.getHost();
450 }
451
452 /***
453 * Returns the default port.
454 *
455 * @return The default port.
456 *
457 * @deprecated use #getHostConfiguration()
458 */
459 public int getPort() {
460 return hostConfiguration.getPort();
461 }
462
463 /***
464 * Returns the {@link HostConfiguration host configuration} associated with the
465 * HttpClient.
466 *
467 * @return {@link HostConfiguration host configuration}
468 *
469 * @since 2.0
470 */
471 public synchronized HostConfiguration getHostConfiguration() {
472 return hostConfiguration;
473 }
474
475 /***
476 * Assigns the {@link HostConfiguration host configuration} to use with the
477 * HttpClient.
478 *
479 * @param hostConfiguration The {@link HostConfiguration host configuration} to set
480 *
481 * @since 2.0
482 */
483 public synchronized void setHostConfiguration(HostConfiguration hostConfiguration) {
484 this.hostConfiguration = hostConfiguration;
485 }
486
487 /***
488 * Returns the {@link HttpConnectionManager HTTP connection manager} associated
489 * with the HttpClient.
490 *
491 * @return {@link HttpConnectionManager HTTP connection manager}
492 *
493 * @since 2.0
494 */
495 public synchronized HttpConnectionManager getHttpConnectionManager() {
496 return httpConnectionManager;
497 }
498
499 /***
500 * Assigns the {@link HttpConnectionManager HTTP connection manager} to use with
501 * the HttpClient.
502 *
503 * @param httpConnectionManager The {@link HttpConnectionManager HTTP connection manager}
504 * to set
505 *
506 * @since 2.0
507 */
508 public synchronized void setHttpConnectionManager(
509 HttpConnectionManager httpConnectionManager
510 ) {
511 this.httpConnectionManager = httpConnectionManager;
512 if (this.httpConnectionManager != null) {
513 this.httpConnectionManager.getParams().setDefaults(this.params);
514 }
515 }
516
517 /***
518 * Returns {@link HttpClientParams HTTP protocol parameters} associated with this HttpClient.
519 *
520 * @since 3.0
521 *
522 * @see HttpClientParams
523 */
524 public HttpClientParams getParams() {
525 return this.params;
526 }
527
528 /***
529 * Assigns {@link HttpClientParams HTTP protocol parameters} for this HttpClient.
530 *
531 * @since 3.0
532 *
533 * @see HttpClientParams
534 */
535 public void setParams(final HttpClientParams params) {
536 if (params == null) {
537 throw new IllegalArgumentException("Parameters may not be null");
538 }
539 this.params = params;
540 }
541
542 }