KickJava   Java API By Example, From Geeks To Geeks.

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


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.BufferedInputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.InterruptedIOException JavaDoc;
28 import java.io.OutputStream JavaDoc;
29 import java.net.Socket JavaDoc;
30 import java.net.UnknownHostException JavaDoc;
31 import java.text.MessageFormat JavaDoc;
32 import java.text.SimpleDateFormat JavaDoc;
33 import java.util.Date JavaDoc;
34
35 import com.maverick.ssl.SSLException;
36 import com.maverick.ssl.SSLIOException;
37 import com.maverick.ssl.SSLTransportFactory;
38
39 /**
40  *
41  * @author Lee David Painter <a HREF="mailto:lee@3sp.com">&lt;lee@3sp.com&gt;</a>
42  */

43 public class HttpConnection {
44
45     SocketWithLayeredTransport socket;
46     InputStream JavaDoc in;
47     OutputStream JavaDoc out;
48     OutputStream JavaDoc monitorInOut;
49     OutputStream JavaDoc monitorOutOut;
50     HttpClient client;
51     boolean isClosed = false;
52     boolean canReuse = true;
53     boolean keepAlive = true;
54     long lastAccessed;
55     HttpAuthenticator authenticator;
56     boolean monitoring = "true".equals(System.getProperty("http.connection.debug")); //$NON-NLS-1$ //$NON-NLS-2$
57

58     public static final int CONNECTION_TIMEOUT_LIMIT = 120000;
59     private static int sequence = 0;
60     private static SimpleDateFormat JavaDoc f = new SimpleDateFormat JavaDoc("HH-mm-ss-SS"); //$NON-NLS-1$
61
private static Object JavaDoc lock = new Object JavaDoc();
62
63     private static boolean linger = true;
64     private static boolean noDelay = false;
65     private boolean isPooled = true;
66
67     // #ifdef DEBUG
68
static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(HttpConnection.class);
69
70     // #endif
71

72     public HttpConnection(HttpClient client) throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException,
73         UnsupportedAuthenticationException, AuthenticationCancelledException {
74         this.client = client;
75         reconnect();
76     }
77     
78     public HttpConnection(HttpClient client, SocketWithLayeredTransport socket) throws IOException JavaDoc {
79         this.client = client;
80         this.socket = socket;
81         this.isPooled = false;
82         
83         int lingerTime = socket.getSoLinger();
84         socket.setSoLinger(linger, false ? 0 : (lingerTime == -1 ? 0 : lingerTime));
85
86         in = new HttpConnectionInputStream(socket.getInputStream(), 32768);
87         out = new HttpConnectionOutputStream();
88
89         isClosed = false;
90         canReuse = true;
91         
92     }
93
94     public static void setDefaultSoLinger(boolean linger) {
95         HttpConnection.linger = linger;
96     }
97
98     public static void setDefaultNoDelay(boolean noDelay) {
99         HttpConnection.noDelay = noDelay;
100     }
101
102     public synchronized void reconnect() throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException,
103                     UnsupportedAuthenticationException, AuthenticationCancelledException {
104         close();
105         if (!client.isProxyConfigured()) {
106             // #ifdef DEBUG
107
log.debug(MessageFormat.format(Messages.getString("HttpConnection.connectingTo"), new Object JavaDoc[] { client.hostname, new Integer JavaDoc(client.port) })); //$NON-NLS-1$
108
// #endif
109
this.socket = SocketWithLayeredTransportFactory.getDefault().createSocket(client.hostname, client.port);
110             this.socket.setTcpNoDelay(noDelay);
111             
112             // LDP - Always push a transport even if its null. This allows us to pick up
113
// a start event in child implementations of the socket so we can decide
114
// when to start streaming across forwarded sockets that may or may not
115
// require an SSL transport.
116
this.socket.pushTransport(client.isSecure ? SSLTransportFactory.newInstance() : null);
117             
118         } else {
119
120             synchronized (client) {
121                 switch (client.proxyType) {
122                     case HttpClient.PROXY_HTTP:
123                     case HttpClient.PROXY_HTTPS:
124
125                         // #ifdef DEBUG
126
log.debug(MessageFormat.format(Messages.getString("HttpConnection.proxyConnect"), new Object JavaDoc[] { client.hostname, new Integer JavaDoc(client.port), client.proxyType == HttpClient.PROXY_HTTPS ? "https" : "http", client.proxyHost, new Integer JavaDoc(client.proxyPort) })); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
127
// #endif
128
// Setup the proxy client connection
129
if (client.proxyClient == null) {
130                             client.proxyClient = new HttpClient(client);
131                         }
132
133                         ConnectMethod proxyConnect = new ConnectMethod(client.hostname, client.port, client.isSecure);
134                         // Execute and retreive the direct socket
135
HttpResponse response = client.proxyClient.execute(proxyConnect);
136
137                         if (response.getStatus() == 200) {
138                             socket = response.getConnection().socket;
139                         } else
140                             throw new IOException JavaDoc(MessageFormat.format(Messages.getString("HttpConnection.invalidHttpStatusCode"), new Object JavaDoc[] { new Integer JavaDoc(response.getStatus()) })); //$NON-NLS-1$
141
break;
142                     default:
143                         throw new IllegalArgumentException JavaDoc(MessageFormat.format(Messages.getString("HttpConnection.invalidProxyType"), new Object JavaDoc[] { new Integer JavaDoc(client.proxyType) })); //$NON-NLS-1$
144
}
145             }
146         }
147
148         int lingerTime = socket.getSoLinger();
149         socket.setSoLinger(linger, false ? 0 : (lingerTime == -1 ? 0 : lingerTime));
150
151         in = new HttpConnectionInputStream(socket.getInputStream(), 32768);
152         out = new HttpConnectionOutputStream();
153
154         isClosed = false;
155         canReuse = true;
156     }
157
158     public boolean isMonitoring() {
159         return monitoring;
160     }
161
162     void monitor(String JavaDoc uri) throws IOException JavaDoc {
163         File JavaDoc dir = new File JavaDoc(System.getProperty("java.io.tmpdir"), client.getHost() + "." + client.getPort()); //$NON-NLS-1$ //$NON-NLS-2$
164
if (!dir.exists() && !dir.mkdirs()) {
165             // #ifdef DEBUG
166
log.error(MessageFormat.format(Messages.getString("HttpConnection.failedToCreateMaverickDebugDirectory"), new Object JavaDoc[] { dir })); //$NON-NLS-1$
167
// #endif
168
} else {
169             synchronized (lock) {
170                 File JavaDoc inFile = new File JavaDoc(dir, String.valueOf(sequence) + "_" + f.format(new Date JavaDoc()) + //$NON-NLS-1$
171
".response.log"); //$NON-NLS-1$
172
File JavaDoc outFile = new File JavaDoc(dir, String.valueOf(sequence) + "_" + f.format(new Date JavaDoc()) + //$NON-NLS-1$
173
".request.log"); //$NON-NLS-1$
174
monitorInOut = new FileOutputStream JavaDoc(inFile);
175                 monitorOutOut = new FileOutputStream JavaDoc(outFile);
176                 in = new MonitorInputStream(new HttpConnectionInputStream(socket.getInputStream(), 32768), monitorInOut);
177                 out = new MonitorOutputStream(new HttpConnectionOutputStream(), monitorOutOut);
178
179                 sequence++;
180             }
181         }
182     }
183
184     void stopMonitor() throws IOException JavaDoc {
185
186         try {
187             in.close();
188         } catch (IOException JavaDoc ex) {
189         }
190         try {
191             out.close();
192         } catch (IOException JavaDoc ex) {
193         }
194         in = socket.getInputStream();
195         out = new HttpConnectionOutputStream();
196     }
197
198     void updateState() {
199         this.lastAccessed = System.currentTimeMillis();
200     }
201
202     void release() {
203
204         try {
205             if (monitoring)
206                 stopMonitor();
207         } catch (IOException JavaDoc ex) {
208         }
209
210         if (!canReuse)
211             close();
212         
213         if(isPooled)
214             client.connections.releaseConnection(this);
215     }
216
217     void verify() throws UnknownHostException JavaDoc, IOException JavaDoc, HttpException, UnsupportedAuthenticationException,
218                     AuthenticationCancelledException {
219
220         try {
221
222             if (System.currentTimeMillis() > lastAccessed + CONNECTION_TIMEOUT_LIMIT)
223                 canReuse = false;
224             else {
225
226                 try {
227                     socket.setSoTimeout(1);
228                     in.mark(1);
229                     int byteRead = in.read();
230                     if (byteRead == -1) {
231                         // again - if the socket is reporting all data read,
232
// probably stale
233
// #ifdef DEBUG
234
log.debug(Messages.getString("HttpConnection.eof")); //$NON-NLS-1$
235
// #endif
236
canReuse = false;
237                     } else {
238                         in.reset();
239                     }
240                 } finally {
241                     socket.setSoTimeout(0);
242                 }
243             }
244         } catch (InterruptedIOException JavaDoc ex) {
245             // Connection should be ok
246
} catch (SSLIOException ex) {
247             canReuse = (ex.getRealException().getStatus() == SSLException.READ_TIMEOUT);
248         } catch (IOException JavaDoc ex) {
249             // Connection is dead
250
// #ifdef DEBUG
251
log.debug(Messages.getString("HttpConnection.dead")); //$NON-NLS-1$
252
// #endif
253
canReuse = false;
254
255         }
256
257         if (!canReuse && isPooled)
258             reconnect();
259     }
260
261     public boolean isClosed() {
262         return isClosed;
263     }
264
265     public boolean isKeepAlive() {
266         return keepAlive;
267     }
268
269     public boolean canReuse() {
270         return canReuse;
271     }
272
273     public synchronized void close() {
274         try {
275             try {
276                 if (socket != null)
277                     socket.close();
278             } catch (IOException JavaDoc ex) {
279             }
280         } finally {
281             if (monitorInOut != null) {
282                 try {
283                     monitorInOut.close();
284                 } catch (IOException JavaDoc ioe) {
285                 }
286             }
287             if (monitorOutOut != null) {
288                 try {
289                     monitorOutOut.close();
290                 } catch (IOException JavaDoc ioe) {
291                 }
292             }
293         }
294
295         isClosed = true;
296     }
297
298     public OutputStream JavaDoc getOutputStream() throws IOException JavaDoc {
299         return out;
300         // return socket.getOutputStream();
301
}
302
303     public InputStream JavaDoc getInputStream() throws IOException JavaDoc {
304         return in;
305     }
306
307     public int getPort() {
308         return client.port;
309     }
310
311     public String JavaDoc getHost() {
312         return client.hostname;
313     }
314
315     public String JavaDoc getHostHeaderValue() {
316         return client.hostname
317             + ((client.isSecure && client.port != 443) || (!client.isSecure && client.port != 80) ? (":" + client.port) : ""); //$NON-NLS-1$ //$NON-NLS-2$
318
}
319
320     public boolean isSecure() {
321         return client.isSecure;
322     }
323
324     public Socket JavaDoc getSocket() {
325         return socket;
326     }
327
328     public void setAuthenticator(HttpAuthenticator authenticator) {
329         this.authenticator = authenticator;
330     }
331
332     public HttpAuthenticator getAuthenticator() {
333         return authenticator;
334     }
335
336     class HttpConnectionInputStream extends BufferedInputStream JavaDoc {
337
338         HttpConnectionInputStream(InputStream JavaDoc in, int len) {
339             super(in, len);
340         }
341
342         public void close() throws IOException JavaDoc {
343             updateState();
344             socket.getInputStream().close();
345         }
346
347         public int read() throws IOException JavaDoc {
348             updateState();
349             return super.read();
350         }
351
352         public int read(byte[] buf, int off, int len) throws IOException JavaDoc {
353             updateState();
354             return super.read(buf, off, len);
355         }
356     }
357
358     class HttpConnectionOutputStream extends OutputStream JavaDoc {
359
360         public void close() throws IOException JavaDoc {
361             updateState();
362             socket.getOutputStream().close();
363         }
364
365         public void write(int b) throws IOException JavaDoc {
366             updateState();
367             socket.getOutputStream().write(b);
368         }
369
370         public void write(byte[] buf, int off, int len) throws IOException JavaDoc {
371             updateState();
372             socket.getOutputStream().write(buf, off, len);
373         }
374     }
375
376     class MonitorInputStream extends InputStream JavaDoc {
377
378         InputStream JavaDoc in = null;
379         OutputStream JavaDoc monitorOut;
380
381         MonitorInputStream(InputStream JavaDoc in, OutputStream JavaDoc monitorOut) {
382             super();
383             this.in = in;
384             this.monitorOut = monitorOut;
385         }
386
387         /*
388          * (non-Javadoc)
389          *
390          * @see java.io.InputStream#available()
391          */

392         public int available() throws IOException JavaDoc {
393             return in.available();
394         }
395
396         /*
397          * (non-Javadoc)
398          *
399          * @see java.io.InputStream#close()
400          */

401         public void close() throws IOException JavaDoc {
402             in.close();
403         }
404
405         /*
406          * (non-Javadoc)
407          *
408          * @see java.io.InputStream#mark(int)
409          */

410         public synchronized void mark(int readlimit) {
411             in.mark(readlimit);
412         }
413
414         /*
415          * (non-Javadoc)
416          *
417          * @see java.io.InputStream#markSupported()
418          */

419         public boolean markSupported() {
420             return in.markSupported();
421         }
422
423         /*
424          * (non-Javadoc)
425          *
426          * @see java.io.InputStream#read(byte[], int, int)
427          */

428         public int read(byte[] b, int off, int len) throws IOException JavaDoc {
429             int r = in.read(b, off, len);
430             if (r != -1) {
431                 try {
432                     monitorOut.write(b, off, r);
433                     monitorOut.flush();
434                 } catch (IOException JavaDoc ioe) {
435                 }
436             }
437             return r;
438         }
439
440         /*
441          * (non-Javadoc)
442          *
443          * @see java.io.InputStream#read(byte[])
444          */

445         public int read(byte[] b) throws IOException JavaDoc {
446             int r = in.read(b);
447             if (r != -1) {
448                 try {
449                     monitorOut.write(b, 0, r);
450                     monitorOut.flush();
451                 } catch (IOException JavaDoc ioe) {
452                 }
453             }
454             return r;
455         }
456
457         /*
458          * (non-Javadoc)
459          *
460          * @see java.io.InputStream#reset()
461          */

462         public synchronized void reset() throws IOException JavaDoc {
463             in.reset();
464         }
465
466         /*
467          * (non-Javadoc)
468          *
469          * @see java.io.InputStream#skip(long)
470          */

471         public long skip(long n) throws IOException JavaDoc {
472             return in.skip(n);
473         }
474
475         public int read() throws IOException JavaDoc {
476             int r = in.read();
477             if (r != -1) {
478                 try {
479                     monitorOut.write(r);
480                     monitorOut.flush();
481                 } catch (IOException JavaDoc ioe) {
482                 }
483             }
484             return r;
485         }
486
487     }
488
489     class MonitorOutputStream extends OutputStream JavaDoc {
490
491         OutputStream JavaDoc out;
492         OutputStream JavaDoc monitorOut;
493
494         MonitorOutputStream(OutputStream JavaDoc out, OutputStream JavaDoc monitorOut) {
495             super();
496             this.out = out;
497             this.monitorOut = monitorOut;
498         }
499
500         /*
501          * (non-Javadoc)
502          *
503          * @see java.io.OutputStream#close()
504          */

505         public void close() throws IOException JavaDoc {
506             out.close();
507         }
508
509         /*
510          * (non-Javadoc)
511          *
512          * @see java.io.OutputStream#flush()
513          */

514         public void flush() throws IOException JavaDoc {
515             out.flush();
516         }
517
518         /*
519          * (non-Javadoc)
520          *
521          * @see java.io.OutputStream#write(byte[], int, int)
522          */

523         public void write(byte[] b, int off, int len) throws IOException JavaDoc {
524             out.write(b, off, len);
525             try {
526                 monitorOut.write(b, off, len);
527                 monitorOut.flush();
528             } catch (IOException JavaDoc ioe) {
529             }
530         }
531
532         /*
533          * (non-Javadoc)
534          *
535          * @see java.io.OutputStream#write(byte[])
536          */

537         public void write(byte[] b) throws IOException JavaDoc {
538             out.write(b);
539             try {
540                 monitorOut.write(b);
541                 monitorOut.flush();
542             } catch (IOException JavaDoc ioe) {
543             }
544         }
545
546         public void write(int b) throws IOException JavaDoc {
547             out.write(b);
548             try {
549                 monitorOut.write(b);
550                 monitorOut.flush();
551             } catch (IOException JavaDoc ioe) {
552             }
553         }
554
555     }
556
557     public void setCanReuse(boolean canReuse) {
558         this.canReuse = canReuse;
559     }
560 }
561
Popular Tags