KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > maverick > http > HttpClient


1 /*
2  * SSL-Explorer
3  *
4  * Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */

19             
20 package com.maverick.http;
21
22 import java.io.EOFException JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.net.UnknownHostException JavaDoc;
25 import java.text.MessageFormat JavaDoc;
26 import java.util.Date JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.StringTokenizer JavaDoc;
29 import java.util.Vector JavaDoc;
30
31 /**
32  *
33  * @author Lee David Painter <a HREF="mailto:lee@3sp.com">&lt;lee@3sp.com&gt;</a>
34  */

35 public class HttpClient {
36
37     static final String JavaDoc PROXY_AUTHORIZATION = "Proxy-Authorization";
38     static final String JavaDoc AUTHORIZATION = "Authorization";
39     static final String JavaDoc WWW_AUTHENTICATE = "WWW-Authenticate";
40     static final String JavaDoc PROXY_AUTHENTICATE = "Proxy-Authenticate";
41     
42     public static final int PROXY_NONE = 0;
43     public static final int PROXY_HTTP = 1;
44     public static final int PROXY_HTTPS = 2;
45
46     public static String JavaDoc USER_AGENT = "Maverick-HttpClient/1.0"; //$NON-NLS-1$
47

48     /**
49      * The target server
50      */

51     String JavaDoc hostname;
52     int port;
53     boolean isSecure;
54     PasswordCredentials credentials;
55     AuthenticationPrompt prompt;
56     String JavaDoc preferedAuthentication = HttpAuthenticatorFactory.BASIC;
57     boolean preemptiveAuthentication = false;
58     HttpConnectionManager connections = new HttpConnectionManager(this);
59     boolean includeCookies = true;
60     Vector JavaDoc cookies = new Vector JavaDoc();
61     int maxAuthenticationAttempts = 5;
62     int proxyMaxAuthenticationAttempts = 5;
63     boolean proxyPreemptiveAuthentication = false;
64     HttpClient proxyClient;
65     boolean credentialsFailed = false;
66
67     /**
68      * Proxy information
69      */

70     String JavaDoc proxyHost;
71     int proxyPort = -1;
72     int proxyType = PROXY_NONE;
73
74     PasswordCredentials proxyCredentials;
75     AuthenticationPrompt proxyAuthenticationPrompt;
76     String JavaDoc proxyPreferedAuthentication = HttpAuthenticatorFactory.BASIC;
77     boolean isProxyClient = false;
78
79     // #ifdef DEBUG
80
static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(HttpClient.class);
81
82     // #endif
83

84     public HttpClient(String JavaDoc hostname, int port, boolean isSecure) {
85         this.hostname = hostname;
86         this.port = port;
87         this.isSecure = isSecure;
88
89     }
90
91     /**
92      * Set the default user agent.
93      *
94      * @param userAgent default user agent
95      */

96     public static void setUserAgent(String JavaDoc userAgent) {
97         USER_AGENT = userAgent;
98     }
99
100     HttpClient(HttpClient client) {
101         this(client.proxyHost, client.proxyPort, client.proxyType == HttpClient.PROXY_HTTPS);
102         setAuthenticationPrompt(client.proxyAuthenticationPrompt);
103         setCredentials(client.proxyCredentials);
104         setMaxAuthenticationAttempts(client.proxyMaxAuthenticationAttempts);
105         setPreemtiveAuthentication(client.proxyPreemptiveAuthentication);
106         setPreferredAuthentication(client.proxyPreferedAuthentication);
107         this.isProxyClient = true;
108     }
109
110     boolean configureProxy() {
111         /**
112          * Attempt to automatically configure proxy from Maverick SSL proxy
113          * settings
114          */

115         if (!isProxyClient && !isNonProxiedHost(hostname)) {
116             if (System.getProperty("com.maverick.ssl.https.HTTPProxyHostname") != null) { //$NON-NLS-1$
117
setProxyHost(System.getProperty("com.maverick.ssl.https.HTTPProxyHostname")); //$NON-NLS-1$
118
// #ifdef DEBUG
119
log.debug(MessageFormat.format(Messages.getString("HttpClient.setClientProxyHost"), new Object JavaDoc[] { proxyHost })); //$NON-NLS-1$
120
// #endif
121

122                 if (System.getProperty("com.maverick.ssl.https.HTTPProxyPort") != null) { //$NON-NLS-1$
123
setProxyPort(Integer.parseInt(System.getProperty("com.maverick.ssl.https.HTTPProxyPort"))); //$NON-NLS-1$
124
// #ifdef DEBUG
125
log.debug(MessageFormat.format(Messages.getString("HttpClient.setClientProxyPort"), new Object JavaDoc[] { new Integer JavaDoc(proxyPort) })); //$NON-NLS-1$
126
// #endif
127
} else
128                     setProxyPort(80);
129
130                 if (System.getProperty("com.maverick.ssl.https.HTTPProxySecure") != null) { //$NON-NLS-1$
131
setProxyType(System.getProperty("com.maverick.ssl.https.HTTPProxySecure").equalsIgnoreCase("true") ? PROXY_HTTPS //$NON-NLS-1$ //$NON-NLS-2$
132
: PROXY_HTTP);
133                 } else
134                     setProxyType(PROXY_HTTP);
135
136                 if (System.getProperty("com.maverick.ssl.https.HTTPProxyUsername") != null) { //$NON-NLS-1$
137
setProxyCredentials(new PasswordCredentials(System.getProperty("com.maverick.ssl.https.HTTPProxyUsername"),
138                             System.getProperty("com.maverick.ssl.https.HTTPProxyPassword")==null ? "" : System.getProperty("com.maverick.ssl.https.HTTPProxyPassword")));
139                 }
140                 
141                 return true;
142             }
143         }
144
145         return false;
146     }
147
148     public boolean isProxyConfigured() {
149         if (proxyType == PROXY_NONE)
150             return configureProxy();
151         else
152             return true;
153     }
154
155     public static boolean isNonProxiedHost(String JavaDoc host) {
156         String JavaDoc nonProxiedHosts = System.getProperty("com.maverick.ssl.https.HTTPProxyNonProxyHosts"); //$NON-NLS-1$
157
if (nonProxiedHosts == null || nonProxiedHosts.equals("")) { //$NON-NLS-1$
158
return false;
159         }
160         StringTokenizer JavaDoc t = new StringTokenizer JavaDoc(nonProxiedHosts, "|"); //$NON-NLS-1$
161
while (t.hasMoreTokens()) {
162             String JavaDoc token = t.nextToken();
163             int idx = token.indexOf('*');
164             if (idx != -1) {
165                 if (token.length() == 1) {
166                     return true;
167                 }
168                 String JavaDoc before = token.substring(0, idx);
169                 String JavaDoc after = token.substring(idx + 1);
170                 if (((before.length() == 0) || host.startsWith(before)) && ((after.length() == 0) || host.endsWith(after))) {
171                     return true;
172                 }
173             } else {
174                 if (host.equalsIgnoreCase(token)) {
175                     return true;
176                 }
177             }
178         }
179         return false;
180     }
181
182     public HttpConnectionManager getConnectionManager() {
183         return connections;
184     }
185
186     public String JavaDoc getHost() {
187         return hostname;
188     }
189
190     public int getPort() {
191         return port;
192     }
193
194     public boolean isSecure() {
195         return isSecure;
196     }
197
198     public void setMaxAuthenticationAttempts(int maxAuthenticationAttempts) {
199         this.maxAuthenticationAttempts = maxAuthenticationAttempts;
200     }
201
202     public void setProxyHost(String JavaDoc proxyHost) {
203         this.proxyHost = proxyHost;
204     }
205
206     public void setProxyPort(int proxyPort) {
207         this.proxyPort = proxyPort;
208     }
209
210     public void setProxyMaxAuthenticationAttempts(int proxyMaxAuthenticationAttempts) {
211         this.proxyMaxAuthenticationAttempts = proxyMaxAuthenticationAttempts;
212     }
213
214     public void setProxyType(int proxyType) {
215         if (proxyType > PROXY_HTTPS || proxyType < PROXY_NONE) {
216             throw new IllegalArgumentException JavaDoc(MessageFormat.format(Messages.getString("HttpClient.notValidProxyType"), new Object JavaDoc[] { new Integer JavaDoc(proxyType) })); //$NON-NLS-1$
217
}
218         this.proxyType = proxyType;
219     }
220
221     public void setProxyCredentials(PasswordCredentials proxyCredentials) {
222         this.proxyCredentials = proxyCredentials;
223     }
224
225     public void setProxyPreemptiveAuthentication(boolean proxyPreemptiveAuthentication) {
226         this.proxyPreemptiveAuthentication = proxyPreemptiveAuthentication;
227     }
228
229     public void setProxyAuthenticationPrompt(AuthenticationPrompt proxyAuthenticationPrompt) {
230         this.proxyAuthenticationPrompt = proxyAuthenticationPrompt;
231     }
232
233     public void setProxyPreferedAuthentication(String JavaDoc scheme) {
234         this.proxyPreferedAuthentication = scheme;
235     }
236
237     public void setAuthenticationPrompt(AuthenticationPrompt prompt) {
238         this.prompt = prompt;
239     }
240
241     public void setPreferredAuthentication(String JavaDoc scheme) {
242         this.preferedAuthentication = scheme;
243     }
244
245     public void setCredentials(PasswordCredentials credentials) {
246         this.credentials = credentials;
247         credentialsFailed = false;
248     }
249
250     public void close() {
251         connections.closeConnections();
252     }
253
254     synchronized void prepareRequest(HttpRequest request, HttpMethod method, HttpConnection con) throws IOException JavaDoc, HttpException,
255                     UnsupportedAuthenticationException, AuthenticationCancelledException {
256
257         if (con.isMonitoring()) {
258             con.monitor(method.getURI());
259         }
260
261         request.reset();
262
263         if (preemptiveAuthentication && credentials != null) {
264             // Discard old authenticator and create a new one
265
BasicAuthentication authenticator = new BasicAuthentication(method.getURI(), con.getHost(), con.getPort(), con.isSecure());
266             authenticator.setCredentials(credentials);
267             authenticator.setConnection(con);
268             authenticator.setChallenge("Basic"); //$NON-NLS-1$
269
authenticator.setAuthenicationHeader(method.getName().equals("CONNECT") ? PROXY_AUTHENTICATE : WWW_AUTHENTICATE); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
270
authenticator.setAuthorizationHeader(method.getName().equals("CONNECT") ? PROXY_AUTHORIZATION : AUTHORIZATION); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
271
con.setAuthenticator(authenticator);
272         }
273
274         connections.checkConnection(con);
275
276         if (includeCookies) {
277             String JavaDoc cookiesHeader = ""; //$NON-NLS-1$
278
for (Enumeration JavaDoc e = cookies.elements(); e.hasMoreElements();) {
279                 Cookie cookie = (Cookie) e.nextElement();
280
281                 // Evaluate whether the cookie should be included
282
Date JavaDoc now = new Date JavaDoc();
283                 if (cookie.getExpires() == null || cookie.expires.after(now)) {
284                     if (method.getURI().startsWith(cookie.getPath()) && getHost().endsWith(cookie.getDomain())
285                         && (cookie.isSecure() == isSecure || !cookie.isSecure())) {
286                         cookiesHeader += cookie + "; "; //$NON-NLS-1$
287
}
288                 }
289             }
290
291             if (!cookiesHeader.equals("")) { //$NON-NLS-1$
292
request.setHeaderField("Cookie", cookiesHeader); //$NON-NLS-1$
293
}
294         }
295
296         if (con.isKeepAlive())
297             request.setHeaderField("Connection", "Keep-Alive"); //$NON-NLS-1$ //$NON-NLS-2$
298

299         if (con.getAuthenticator() != null && con.getAuthenticator().canAuthenticate()) {
300             // #ifdef DEBUG
301
log.debug(MessageFormat.format(Messages.getString("HttpClient.settingAuthCredentials"), new Object JavaDoc[] { con.getAuthenticator().getScheme() })); //$NON-NLS-1$
302
// #endif
303
try {
304                 request.removeFields(con.getAuthenticator().getAuthorizationHeader());
305                 con.getAuthenticator().authenticate(request, method);
306             } catch (Exception JavaDoc ex) {
307                 // #ifdef DEBUG
308
log.info(Messages.getString("HttpClient.authenticatorException"), ex); //$NON-NLS-1$
309
// #endif
310
con.setAuthenticator(null);
311             }
312         }
313
314     }
315
316     HttpResponse execute(HttpRequest request, HttpMethod method, HttpConnection con) throws IOException JavaDoc, HttpException,
317                     UnsupportedAuthenticationException, AuthenticationCancelledException {
318
319         prepareRequest(request, method, con);
320
321         // #ifdef DEBUG
322
log.info(MessageFormat.format(Messages.getString("HttpClient.executingMethod"), new Object JavaDoc[] { method.getName(), con.getHost() })); //$NON-NLS-1$
323
// #endif
324

325         return processResponse(request, method, con, method.execute(request, con));
326     }
327
328     HttpConnection executeAsync(HttpRequest request, AsyncHttpMethod method, HttpConnection con) throws IOException JavaDoc, HttpException,
329                     UnsupportedAuthenticationException, AuthenticationCancelledException {
330
331         prepareRequest(request, method, con);
332
333         // #ifdef DEBUG
334
log.info(MessageFormat.format(Messages.getString("HttpClient.executingMethod"), new Object JavaDoc[] { method.getName(), con.getHost() })); //$NON-NLS-1$
335
// #endif
336

337         method.executeAsync(request, con);
338
339         return con;
340     }
341
342     synchronized HttpResponse processResponse(HttpRequest request, HttpMethod method, HttpConnection con, HttpResponse response)
343                     throws IOException JavaDoc, HttpException, UnsupportedAuthenticationException, AuthenticationCancelledException {
344
345         
346         // Process any cookies
347
if (includeCookies) {
348             String JavaDoc[] cookies = response.getHeaderFields("Set-Cookie"); //$NON-NLS-1$
349
if (cookies != null) {
350                 for (int i = 0; i < cookies.length; i++) {
351                     this.cookies.addElement(new Cookie(cookies[i]));
352                 }
353             }
354         }
355
356         try {
357             /**
358              * Now process the response to see if we need to handle
359              * authentication
360              */

361             switch (response.getStatus()) {
362                 case 401:
363                 case 407:
364                     if (con.getAuthenticator() != null) {
365                         int success = con.getAuthenticator().processResponse(response);
366
367                         switch (success) {
368                             case HttpAuthenticator.AUTHENTICATION_COMPLETED:
369                                 // w00t we're in
370
return response;
371                             case HttpAuthenticator.AUTHENTICATION_FAILED:
372                                 // Up the number of cycles and try again
373
request.cycles++;
374                                 credentialsFailed = true;
375                                 break;
376                             case HttpAuthenticator.AUTHENTICATION_IN_PROGRESS:
377                             default:
378                                 // Do nothing just keep on authenticating
379
}
380
381                     } else if (credentials == null && prompt == null) {
382                         return response;
383                     }
384
385                     if (con.getAuthenticator() == null || request.cycles < maxAuthenticationAttempts)
386                         return doAuthentication(response.getStatus() == 401 ? WWW_AUTHENTICATE : PROXY_AUTHENTICATE, response //$NON-NLS-1$ //$NON-NLS-2$
387
.getStatus() == 401 ? AUTHORIZATION : PROXY_AUTHORIZATION, request, method, response, //$NON-NLS-1$ //$NON-NLS-2$
388
con);
389                     else
390                         return response;
391                 default:
392                     // Set the authenticator as complete and return
393
if (con.getAuthenticator() != null) {
394                         credentials = con.getAuthenticator().credentials;
395                         con.getAuthenticator().complete();
396                     }
397                     return response;
398
399             }
400         } catch (UnsupportedAuthenticationException ex) {
401             /**
402              * We dont support this type of authentication so return the
403              * response
404              */

405             return response;
406         }
407     }
408
409     private HttpResponse doAuthentication(String JavaDoc authenticateHeader, String JavaDoc authorizationHeader, HttpRequest request,
410                                           HttpMethod method, HttpResponse response, HttpConnection con) throws IOException JavaDoc,
411                     HttpException, UnsupportedAuthenticationException, AuthenticationCancelledException {
412
413         // Check for failed authentication limit
414
if (credentialsFailed) {
415             con.setAuthenticator(null);
416             return response;
417         }
418         // If we're called we are disgaurding the previous response
419
response.close(false);
420
421         // Authorization required
422
String JavaDoc[] challenges = response.getHeaderFields(authenticateHeader);
423
424         if (challenges == null)
425             return response;
426
427         // #ifdef DEBUG
428
for (int i = 0; i < challenges.length; i++) {
429             log.info(MessageFormat.format(Messages.getString("HttpClient.requiresAuthType"), new Object JavaDoc[] { con.getHost(), HttpAuthenticatorFactory.getAuthenticationMethod(challenges[i]) }));//$NON-NLS-1$
430
}
431         // #endif
432

433         /**
434          * If we don't already have an authenticator we should create one
435          */

436         if (credentials == null && prompt == null && con.getAuthenticator() == null) {
437             // We cannot authenticate as we do not have any credentials
438
// or a prompt
439
return response;
440         }
441
442         /**
443          * If we got this far then we can authenticate so try to create an
444          * appropriate authenticator
445          */

446         if (con.getAuthenticator() == null || !con.getAuthenticator().getURI().startsWith(method.getURI())) {
447             con.setAuthenticator(HttpAuthenticatorFactory.createAuthenticator(con,
448                 challenges,
449                 authenticateHeader,
450                 authorizationHeader,
451                 preferedAuthentication,
452                 method.getURI()));
453         }
454
455         if (credentials != null) {
456             // #ifdef DEBUG
457
log.info(Messages.getString("HttpClient.settingUserCreds")); //$NON-NLS-1$
458
// #endif
459
con.getAuthenticator().setCredentials(credentials);
460         } else if (prompt != null && con.getAuthenticator().wantsPrompt()) {
461             // #ifdef DEBUG
462
log.info(Messages.getString("HttpClient.promptingForCreds")); //$NON-NLS-1$
463
// #endif
464
if (!prompt.promptForCredentials(authenticateHeader.equals(PROXY_AUTHENTICATE), con.getAuthenticator())) {
465                 throw new AuthenticationCancelledException();
466             }
467         }
468
469         if (!con.canReuse())
470             con.reconnect();
471
472         try {
473             return execute(request, method, con);
474         } catch (EOFException JavaDoc ex) {
475             // This was possibly caused by the connection not being reusable
476
// This will not work with NTLM
477
con.reconnect();
478             return execute(request, method, con);
479         }
480     }
481
482     public HttpResponse execute(HttpMethod method) throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException,
483                     UnsupportedAuthenticationException, AuthenticationCancelledException {
484         // #ifdef DEBUG
485
log.debug(MessageFormat.format(Messages.getString("HttpClient.executing"), new Object JavaDoc[] { method.getName() })); //$NON-NLS-1$
486
// #endif
487
for (int i = 0; i < 2; i++) {
488             try {
489                 return execute(method, connections.getConnection());
490             } catch (EOFException JavaDoc eof) {
491                 // #ifdef DEBUG
492
if (i != 1) {
493                     log.warn(MessageFormat.format(Messages.getString("HttpClient.eof.attemptingAgain"), new Object JavaDoc[] { new Integer JavaDoc(i) })); //$NON-NLS-1$
494
} else {
495                     log.warn(MessageFormat.format(Messages.getString("HttpClient.eof.givingUp"), new Object JavaDoc[] { new Integer JavaDoc(i) })); //$NON-NLS-1$
496
}
497                 // #endif
498
}
499         }
500         throw new EOFException JavaDoc(Messages.getString("HttpClient.couldNotConnect")); //$NON-NLS-1$
501
}
502     
503     public HttpResponse execute(HttpMethod method, HttpConnection con) throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException,
504     UnsupportedAuthenticationException, AuthenticationCancelledException {
505         return execute(new HttpRequest(), method, con);
506     }
507
508     public HttpConnection executeAsync(AsyncHttpMethod method) throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException,
509                     UnsupportedAuthenticationException, AuthenticationCancelledException {
510         return executeAsync(method, connections.getConnection());
511     }
512     
513     public HttpConnection executeAsync(AsyncHttpMethod method, HttpConnection con) throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException,
514     UnsupportedAuthenticationException, AuthenticationCancelledException {
515         // #ifdef DEBUG
516
log.debug(MessageFormat.format(Messages.getString("HttpClient.executing"), new Object JavaDoc[] { method.getName() })); //$NON-NLS-1$
517
// #endif
518
return executeAsync(new HttpRequest(), method, connections.getConnection());
519     }
520
521
522     public void setIncludeCookies(boolean includeCookies) {
523         this.includeCookies = includeCookies;
524     }
525
526     public void setPreemtiveAuthentication(boolean preemptiveAuthentication) {
527         this.preemptiveAuthentication = preemptiveAuthentication;
528     }
529
530     public void removeAllCookies() {
531         cookies.removeAllElements();
532     }
533 }
534
Popular Tags