1:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59:
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65:
66:
71: public class HTTPConnection
72: {
73:
74:
77: public static final int HTTP_PORT = 80;
78:
79:
82: public static final int HTTPS_PORT = 443;
83:
84: private static final String userAgent = initUserAgent();
85:
86: private static String initUserAgent()
87: {
88: try
89: {
90: StringBuffer buf = new StringBuffer("inetlib/1.1 (");
91: buf.append(System.getProperty("os.name"));
92: buf.append("; ");
93: buf.append(System.getProperty("os.arch"));
94: buf.append("; ");
95: buf.append(System.getProperty("user.language"));
96: buf.append(")");
97: return buf.toString();
98: }
99: catch (SecurityException e)
100: {
101: return "inetlib/1.1";
102: }
103: }
104:
105:
108: protected final String hostname;
109:
110:
113: protected final int port;
114:
115:
118: protected final boolean secure;
119:
120:
123: protected final int connectionTimeout;
124:
125:
128: protected final int timeout;
129:
130:
133: protected String proxyHostname;
134:
135:
138: protected int proxyPort;
139:
140:
143: protected int majorVersion;
144:
145:
148: protected int minorVersion;
149:
150: private final List connectionListeners;
151: private final List requestListeners;
152:
153:
156: protected Socket socket;
157:
158:
161: protected InputStream in;
162:
163:
166: protected OutputStream out;
167:
168:
171: private Map nonceCounts;
172:
173:
176: protected CookieManager cookieManager;
177:
178:
182: public HTTPConnection(String hostname)
183: {
184: this(hostname, HTTP_PORT, false, 0, 0);
185: }
186:
187:
192: public HTTPConnection(String hostname, boolean secure)
193: {
194: this(hostname, secure ? HTTPS_PORT : HTTP_PORT, secure, 0, 0);
195: }
196:
197:
204: public HTTPConnection(String hostname, boolean secure,
205: int connectionTimeout, int timeout)
206: {
207: this(hostname, secure ? HTTPS_PORT : HTTP_PORT, secure,
208: connectionTimeout, timeout);
209: }
210:
211:
216: public HTTPConnection(String hostname, int port)
217: {
218: this(hostname, port, false, 0, 0);
219: }
220:
221:
227: public HTTPConnection(String hostname, int port, boolean secure)
228: {
229: this(hostname, port, secure, 0, 0);
230: }
231:
232:
240: public HTTPConnection(String hostname, int port, boolean secure,
241: int connectionTimeout, int timeout)
242: {
243: this.hostname = hostname;
244: this.port = port;
245: this.secure = secure;
246: this.connectionTimeout = connectionTimeout;
247: this.timeout = timeout;
248: majorVersion = minorVersion = 1;
249: connectionListeners = Collections.synchronizedList(new ArrayList(4));
250: requestListeners = Collections.synchronizedList(new ArrayList(4));
251: }
252:
253:
256: public String getHostName()
257: {
258: return hostname;
259: }
260:
261:
264: public int getPort()
265: {
266: return port;
267: }
268:
269:
272: public boolean isSecure()
273: {
274: return secure;
275: }
276:
277:
281: public String getVersion()
282: {
283: return "HTTP/" + majorVersion + '.' + minorVersion;
284: }
285:
286:
291: public void setVersion(int majorVersion, int minorVersion)
292: {
293: if (majorVersion != 1)
294: {
295: throw new IllegalArgumentException("major version not supported: " +
296: majorVersion);
297: }
298: if (minorVersion < 0 || minorVersion > 1)
299: {
300: throw new IllegalArgumentException("minor version not supported: " +
301: minorVersion);
302: }
303: this.majorVersion = majorVersion;
304: this.minorVersion = minorVersion;
305: }
306:
307:
312: public void setProxy(String hostname, int port)
313: {
314: proxyHostname = hostname;
315: proxyPort = port;
316: }
317:
318:
321: public boolean isUsingProxy()
322: {
323: return (proxyHostname != null && proxyPort > 0);
324: }
325:
326:
330: public void setCookieManager(CookieManager cookieManager)
331: {
332: this.cookieManager = cookieManager;
333: }
334:
335:
338: public CookieManager getCookieManager()
339: {
340: return cookieManager;
341: }
342:
343:
349: public Request newRequest(String method, String path)
350: {
351: if (method == null || method.length() == 0)
352: {
353: throw new IllegalArgumentException("method must have non-zero length");
354: }
355: if (path == null || path.length() == 0)
356: {
357: path = "/";
358: }
359: Request ret = new Request(this, method, path);
360: if ((secure && port != HTTPS_PORT) ||
361: (!secure && port != HTTP_PORT))
362: {
363: ret.setHeader("Host", hostname + ":" + port);
364: }
365: else
366: {
367: ret.setHeader("Host", hostname);
368: }
369: ret.setHeader("User-Agent", userAgent);
370: ret.setHeader("Connection", "keep-alive");
371: ret.setHeader("Accept-Encoding",
372: "chunked;q=1.0, gzip;q=0.9, deflate;q=0.8, " +
373: "identity;q=0.6, *;q=0");
374: if (cookieManager != null)
375: {
376: Cookie[] cookies = cookieManager.getCookies(hostname, secure, path);
377: if (cookies != null && cookies.length > 0)
378: {
379: StringBuffer buf = new StringBuffer();
380: buf.append("$Version=1");
381: for (int i = 0; i < cookies.length; i++)
382: {
383: buf.append(',');
384: buf.append(' ');
385: buf.append(cookies[i].toString());
386: }
387: ret.setHeader("Cookie", buf.toString());
388: }
389: }
390: fireRequestEvent(RequestEvent.REQUEST_CREATED, ret);
391: return ret;
392: }
393:
394:
397: public void close()
398: throws IOException
399: {
400: try
401: {
402: closeConnection();
403: }
404: finally
405: {
406: fireConnectionEvent(ConnectionEvent.CONNECTION_CLOSED);
407: }
408: }
409:
410:
414: protected Socket getSocket()
415: throws IOException
416: {
417: if (socket == null)
418: {
419: String connectHostname = hostname;
420: int connectPort = port;
421: if (isUsingProxy())
422: {
423: connectHostname = proxyHostname;
424: connectPort = proxyPort;
425: }
426: socket = new Socket();
427: InetSocketAddress address =
428: new InetSocketAddress(connectHostname, connectPort);
429: if (connectionTimeout > 0)
430: {
431: socket.connect(address, connectionTimeout);
432: }
433: else
434: {
435: socket.connect(address);
436: }
437: if (timeout > 0)
438: {
439: socket.setSoTimeout(timeout);
440: }
441: if (secure)
442: {
443: try
444: {
445: TrustManager tm = new EmptyX509TrustManager();
446: SSLContext context = SSLContext.getInstance("SSL");
447: TrustManager[] trust = new TrustManager[] { tm };
448: context.init(null, trust, null);
449: SSLSocketFactory factory = context.getSocketFactory();
450: SSLSocket ss =
451: (SSLSocket) factory.createSocket(socket, connectHostname,
452: connectPort, true);
453: String[] protocols = { "TLSv1", "SSLv3" };
454: ss.setEnabledProtocols(protocols);
455: ss.setUseClientMode(true);
456: ss.startHandshake();
457: socket = ss;
458: }
459: catch (GeneralSecurityException e)
460: {
461: throw new IOException(e.getMessage());
462: }
463: }
464: in = socket.getInputStream();
465: in = new BufferedInputStream(in);
466: out = socket.getOutputStream();
467: out = new BufferedOutputStream(out);
468: }
469: return socket;
470: }
471:
472: protected InputStream getInputStream()
473: throws IOException
474: {
475: if (socket == null)
476: {
477: getSocket();
478: }
479: return in;
480: }
481:
482: protected OutputStream getOutputStream()
483: throws IOException
484: {
485: if (socket == null)
486: {
487: getSocket();
488: }
489: return out;
490: }
491:
492:
495: protected void closeConnection()
496: throws IOException
497: {
498: if (socket != null)
499: {
500: try
501: {
502: socket.close();
503: }
504: finally
505: {
506: socket = null;
507: }
508: }
509: }
510:
511:
515: protected String getURI()
516: {
517: StringBuffer buf = new StringBuffer();
518: buf.append(secure ? "https://" : "http://");
519: buf.append(hostname);
520: if (secure)
521: {
522: if (port != HTTPConnection.HTTPS_PORT)
523: {
524: buf.append(':');
525: buf.append(port);
526: }
527: }
528: else
529: {
530: if (port != HTTPConnection.HTTP_PORT)
531: {
532: buf.append(':');
533: buf.append(port);
534: }
535: }
536: return buf.toString();
537: }
538:
539:
543: int getNonceCount(String nonce)
544: {
545: if (nonceCounts == null)
546: {
547: return 0;
548: }
549: return((Integer) nonceCounts.get(nonce)).intValue();
550: }
551:
552:
555: void incrementNonce(String nonce)
556: {
557: int current = getNonceCount(nonce);
558: if (nonceCounts == null)
559: {
560: nonceCounts = new HashMap();
561: }
562: nonceCounts.put(nonce, new Integer(current + 1));
563: }
564:
565:
566:
567: public void addConnectionListener(ConnectionListener l)
568: {
569: synchronized (connectionListeners)
570: {
571: connectionListeners.add(l);
572: }
573: }
574:
575: public void removeConnectionListener(ConnectionListener l)
576: {
577: synchronized (connectionListeners)
578: {
579: connectionListeners.remove(l);
580: }
581: }
582:
583: protected void fireConnectionEvent(int type)
584: {
585: ConnectionEvent event = new ConnectionEvent(this, type);
586: ConnectionListener[] l = null;
587: synchronized (connectionListeners)
588: {
589: l = new ConnectionListener[connectionListeners.size()];
590: connectionListeners.toArray(l);
591: }
592: for (int i = 0; i < l.length; i++)
593: {
594: switch (type)
595: {
596: case ConnectionEvent.CONNECTION_CLOSED:
597: l[i].connectionClosed(event);
598: break;
599: }
600: }
601: }
602:
603: public void addRequestListener(RequestListener l)
604: {
605: synchronized (requestListeners)
606: {
607: requestListeners.add(l);
608: }
609: }
610:
611: public void removeRequestListener(RequestListener l)
612: {
613: synchronized (requestListeners)
614: {
615: requestListeners.remove(l);
616: }
617: }
618:
619: protected void fireRequestEvent(int type, Request request)
620: {
621: RequestEvent event = new RequestEvent(this, type, request);
622: RequestListener[] l = null;
623: synchronized (requestListeners)
624: {
625: l = new RequestListener[requestListeners.size()];
626: requestListeners.toArray(l);
627: }
628: for (int i = 0; i < l.length; i++)
629: {
630: switch (type)
631: {
632: case RequestEvent.REQUEST_CREATED:
633: l[i].requestCreated(event);
634: break;
635: case RequestEvent.REQUEST_SENDING:
636: l[i].requestSent(event);
637: break;
638: case RequestEvent.REQUEST_SENT:
639: l[i].requestSent(event);
640: break;
641: }
642: }
643: }
644:
645: }