KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > HTTPClient > HTTPResponse


1 /*
2  * @(#)HTTPResponse.java 0.3-2 18/06/1999
3  *
4  * This file is part of the HTTPClient package
5  * Copyright (C) 1996-1999 Ronald Tschalär
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free
19  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307, USA
21  *
22  * For questions, suggestions, bug-reports, enhancement-requests etc.
23  * I may be contacted at:
24  *
25  * ronald@innovation.ch
26  *
27  */

28
29 package HTTPClient;
30
31 import java.io.IOException JavaDoc;
32 import java.io.EOFException JavaDoc;
33 import java.io.InterruptedIOException JavaDoc;
34 import java.io.InputStream JavaDoc;
35 import java.io.ByteArrayInputStream JavaDoc;
36 import java.net.URL JavaDoc;
37 import java.util.Date JavaDoc;
38 import java.util.Enumeration JavaDoc;
39
40
41 /**
42  * This defines the http-response class returned by the requests. It's
43  * basically a wrapper around the Response class which first lets all
44  * the modules handle the response before finally giving the info to
45  * the user.
46  *
47  * @version 0.3-2 18/06/1999
48  * @author Ronald Tschalär
49  * @since 0.3
50  */

51
52 public class HTTPResponse implements GlobalConstants, HTTPClientModuleConstants
53 {
54     /** the list of modules */
55     private HTTPClientModule[] modules;
56
57     /** the timeout for reads */
58     private int timeout;
59
60     /** the request */
61     private Request request = null;
62
63     /** the current response */
64     private Response response = null;
65
66     /** the HttpOutputStream to synchronize on */
67     private HttpOutputStream out_stream = null;
68
69     /** our input stream from the stream demux */
70     private InputStream JavaDoc inp_stream;
71
72     /** the status code returned. */
73     private int StatusCode;
74
75     /** the reason line associated with the status code. */
76     private String JavaDoc ReasonLine;
77
78     /** the HTTP version of the response. */
79     private String JavaDoc Version;
80
81     /** the original URI used. */
82     private URI OriginalURI = null;
83
84     /** the final URI of the document. */
85     private URI EffectiveURI = null;
86
87     /** any headers which were received and do not fit in the above list. */
88     private CIHashtable Headers = null;
89
90     /** any trailers which were received and do not fit in the above list. */
91     private CIHashtable Trailers = null;
92
93     /** the ContentLength of the data. */
94     private int ContentLength = -1;
95
96     /** the data (body) returned. */
97     private byte[] Data = null;
98
99     /** signals if we have got and parsed the headers yet? */
100     private boolean initialized = false;
101
102     /** signals if we have got the trailers yet? */
103     private boolean got_trailers = false;
104
105     /** marks this response as aborted (stop() in HTTPConnection) */
106     private boolean aborted = false;
107
108     /** the method used in the request */
109     private String JavaDoc method = null;
110
111
112     // Constructors
113

114     /**
115      * Creates a new HTTPResponse.
116      *
117      * @param modules the list of modules handling this response
118      * @param timeout the timeout to be used on stream read()'s
119      */

120     HTTPResponse(HTTPClientModule[] modules, int timeout, Request orig)
121     {
122     this.modules = modules;
123     this.timeout = timeout;
124     try
125     {
126         this.OriginalURI = new URI(orig.getConnection().getProtocol(),
127                        orig.getConnection().getHost(),
128                        orig.getConnection().getPort(),
129                        orig.getRequestURI());
130     }
131     catch (ParseException pe)
132         { }
133     this.method = orig.getMethod();
134     }
135
136
137     /**
138      * @param req the request
139      * @param resp the response
140      */

141     void set(Request req, Response resp)
142     {
143     this.request = req;
144     this.response = resp;
145     resp.http_resp = this;
146     resp.timeout = timeout;
147     this.aborted = resp.final_resp;
148     }
149
150
151     /**
152      * @param req the request
153      * @param resp the response
154      */

155     void set(Request req, HttpOutputStream out_stream)
156     {
157     this.request = req;
158     this.out_stream = out_stream;
159     }
160
161
162     // Methods
163

164     /**
165      * Give the status code for this request. These are grouped as follows:
166      * <UL>
167      * <LI> 1xx - Informational (new in HTTP/1.1)
168      * <LI> 2xx - Success
169      * <LI> 3xx - Redirection
170      * <LI> 4xx - Client Error
171      * <LI> 5xx - Server Error
172      * </UL>
173      *
174      * @exception IOException if any exception occurs on the socket.
175      * @exception ModuleException if any module encounters an exception.
176      */

177     public final int getStatusCode() throws IOException JavaDoc, ModuleException
178     {
179     if (!initialized) handleResponse();
180     return StatusCode;
181     }
182
183     /**
184      * Give the reason line associated with the status code.
185      *
186      * @exception IOException If any exception occurs on the socket.
187      * @exception ModuleException if any module encounters an exception.
188      */

189     public final String JavaDoc getReasonLine() throws IOException JavaDoc, ModuleException
190     {
191     if (!initialized) handleResponse();
192     return ReasonLine;
193     }
194
195     /**
196      * Get the HTTP version used for the response.
197      *
198      * @exception IOException If any exception occurs on the socket.
199      * @exception ModuleException if any module encounters an exception.
200      */

201     public final String JavaDoc getVersion() throws IOException JavaDoc, ModuleException
202     {
203     if (!initialized) handleResponse();
204     return Version;
205     }
206
207     /**
208      * Get the name and type of server.
209      *
210      * @deprecated This method is a remnant of V0.1; use
211      * <code>getHeader("Server")</code> instead.
212      * @see #getHeader(java.lang.String)
213      * @exception IOException If any exception occurs on the socket.
214      * @exception ModuleException if any module encounters an exception.
215      */

216     public final String JavaDoc getServer() throws IOException JavaDoc, ModuleException
217     {
218     if (!initialized) handleResponse();
219     return getHeader("Server");
220     }
221
222
223     /**
224      * Get the original URI used in the request.
225      *
226      * @return the URI used in primary request
227      */

228     public final URI getOriginalURI()
229     {
230     return OriginalURI;
231     }
232
233
234     /**
235      * Get the final URL of the document. This is set if the original
236      * request was deferred via the "moved" (301, 302, or 303) return
237      * status.
238      *
239      * @return the effective URL, or null if no redirection occured
240      * @exception IOException If any exception occurs on the socket.
241      * @exception ModuleException if any module encounters an exception.
242      * @deprecated use getEffectiveURI() instead
243      * @see #getEffectiveURI
244      */

245     public final URL JavaDoc getEffectiveURL() throws IOException JavaDoc, ModuleException
246     {
247     if (!initialized) handleResponse();
248     if (EffectiveURI != null)
249         return EffectiveURI.toURL();
250     return null;
251     }
252
253
254     /**
255      * Get the final URI of the document. If the request was redirected
256      * via the "moved" (301, 302, 303, or 307) return status this returns
257      * the URI used in the last redirection; otherwise it returns the
258      * original URI.
259      *
260      * @return the effective URI
261      * @exception IOException If any exception occurs on the socket.
262      * @exception ModuleException if any module encounters an exception.
263      */

264     public final URI getEffectiveURI() throws IOException JavaDoc, ModuleException
265     {
266     if (!initialized) handleResponse();
267     if (EffectiveURI != null)
268         return EffectiveURI;
269     return OriginalURI;
270     }
271
272
273     /**
274      * Retrieves the value for a given header.
275      *
276      * @param hdr the header name.
277      * @return the value for the header, or null if non-existent.
278      * @exception IOException If any exception occurs on the socket.
279      * @exception ModuleException if any module encounters an exception.
280      */

281     public String JavaDoc getHeader(String JavaDoc hdr) throws IOException JavaDoc, ModuleException
282     {
283     if (!initialized) handleResponse();
284     return (String JavaDoc) Headers.get(hdr.trim());
285     }
286
287     /**
288      * Retrieves the value for a given header. The value is parsed as an
289      * int.
290      *
291      * @param hdr the header name.
292      * @return the value for the header if the header exists
293      * @exception NumberFormatException if the header's value is not a number
294      * or if the header does not exist.
295      * @exception IOException if any exception occurs on the socket.
296      * @exception ModuleException if any module encounters an exception.
297      */

298     public int getHeaderAsInt(String JavaDoc hdr)
299         throws IOException JavaDoc, ModuleException, NumberFormatException JavaDoc
300     {
301     return Integer.parseInt(getHeader(hdr));
302     }
303
304     /**
305      * Retrieves the value for a given header. The value is parsed as a
306      * date; if this fails it is parsed as a long representing the number
307      * of seconds since 12:00 AM, Jan 1st, 1970. If this also fails an
308      * exception is thrown.
309      * <br>Note: When sending dates use Util.httpDate().
310      *
311      * @param hdr the header name.
312      * @return the value for the header, or null if non-existent.
313      * @exception IllegalArgumentException if the header's value is neither a
314      * legal date nor a number.
315      * @exception IOException if any exception occurs on the socket.
316      * @exception ModuleException if any module encounters an exception.
317      */

318     public Date JavaDoc getHeaderAsDate(String JavaDoc hdr)
319         throws IOException JavaDoc, IllegalArgumentException JavaDoc, ModuleException
320     {
321     String JavaDoc raw_date = getHeader(hdr);
322     if (raw_date == null) return null;
323
324     // asctime() format is missing an explicit GMT specifier
325
if (raw_date.toUpperCase().indexOf("GMT") == -1)
326         raw_date += " GMT";
327
328     Date JavaDoc date;
329
330     try
331         { date = new Date JavaDoc(raw_date); }
332     catch (IllegalArgumentException JavaDoc iae)
333     {
334         // some servers erroneously send a number, so let's try that
335
long time;
336         try
337         { time = Long.parseLong(raw_date); }
338         catch (NumberFormatException JavaDoc nfe)
339         { throw iae; } // give up
340
if (time < 0) time = 0;
341         date = new Date JavaDoc(time * 1000L);
342     }
343
344     return date;
345     }
346
347     /**
348      * Returns an enumeration of all the headers available via getHeader().
349      *
350      * @exception IOException If any exception occurs on the socket.
351      * @exception ModuleException if any module encounters an exception.
352      */

353     public Enumeration JavaDoc listHeaders() throws IOException JavaDoc, ModuleException
354     {
355     if (!initialized) handleResponse();
356     return Headers.keys();
357     }
358
359
360     /**
361      * Retrieves the value for a given trailer. This should not be invoked
362      * until all response data has been read. If invoked before it will
363      * call <code>getData()</code> to force the data to be read.
364      *
365      * @param trailer the trailer name.
366      * @return the value for the trailer, or null if non-existent.
367      * @exception IOException If any exception occurs on the socket.
368      * @exception ModuleException if any module encounters an exception.
369      * @see #getData()
370      */

371     public String JavaDoc getTrailer(String JavaDoc trailer) throws IOException JavaDoc, ModuleException
372     {
373     if (!got_trailers) getTrailers();
374     return (String JavaDoc) Trailers.get(trailer.trim());
375     }
376
377     /**
378      * Retrieves the value for a given tailer. The value is parsed as an
379      * int.
380      *
381      * @param trailer the tailer name.
382      * @return the value for the trailer if the trailer exists
383      * @exception NumberFormatException if the trailer's value is not a number
384      * or if the trailer does not exist.
385      * @exception IOException if any exception occurs on the socket.
386      * @exception ModuleException if any module encounters an exception.
387      */

388     public int getTrailerAsInt(String JavaDoc trailer)
389         throws IOException JavaDoc, ModuleException, NumberFormatException JavaDoc
390     {
391     return Integer.parseInt(getTrailer(trailer));
392     }
393
394     /**
395      * Retrieves the value for a given trailer. The value is parsed as a
396      * date; if this fails it is parsed as a long representing the number
397      * of seconds since 12:00 AM, Jan 1st, 1970. If this also fails an
398      * IllegalArgumentException is thrown.
399      * <br>Note: When sending dates use Util.httpDate().
400      *
401      * @param trailer the trailer name.
402      * @return the value for the trailer, or null if non-existent.
403      * @exception IllegalArgumentException if the trailer's value is neither a
404      * legal date nor a number.
405      * @exception IOException if any exception occurs on the socket.
406      * @exception ModuleException if any module encounters an exception.
407      */

408     public Date JavaDoc getTrailerAsDate(String JavaDoc trailer)
409         throws IOException JavaDoc, IllegalArgumentException JavaDoc, ModuleException
410     {
411     String JavaDoc raw_date = getTrailer(trailer);
412     if (raw_date == null) return null;
413
414     // asctime() format is missing an explicit GMT specifier
415
if (raw_date.toUpperCase().indexOf("GMT") == -1)
416         raw_date += " GMT";
417
418     Date JavaDoc date;
419
420     try
421         { date = new Date JavaDoc(raw_date); }
422     catch (IllegalArgumentException JavaDoc iae)
423     {
424         // some servers erroneously send a number, so let's try that
425
long time;
426         try
427         { time = Long.parseLong(raw_date); }
428         catch (NumberFormatException JavaDoc nfe)
429         { throw iae; } // give up
430
if (time < 0) time = 0;
431         date = new Date JavaDoc(time * 1000L);
432     }
433
434     return date;
435     }
436
437     /**
438      * Returns an enumeration of all the trailers available via getTrailer().
439      *
440      * @exception IOException If any exception occurs on the socket.
441      * @exception ModuleException if any module encounters an exception.
442      */

443     public Enumeration JavaDoc listTrailers() throws IOException JavaDoc, ModuleException
444     {
445     if (!got_trailers) getTrailers();
446     return Trailers.keys();
447     }
448
449
450     /**
451      * Reads all the response data into a byte array. Note that this method
452      * won't return until <em>all</em> the data has been received (so for
453      * instance don't invoke this method if the server is doing a server
454      * push). If <code>getInputStream()</code> had been previously invoked
455      * then this method only returns any unread data remaining on the stream
456      * and then closes it.
457      *
458      * <P>Note to the unwarry: code like
459      * <code>System.out.println("The data: " + resp.getData())</code>
460      * will probably not do what you want - use
461      * <code>System.out.println("The data: " + new String(resp.getData()))</code>
462      * instead.
463      *
464      * @see #getInputStream()
465      * @return an array containing the data (body) returned. If no data
466      * was returned then it's set to a zero-length array.
467      * @exception IOException If any io exception occured while reading
468      * the data
469      * @exception ModuleException if any module encounters an exception.
470      */

471     public synchronized byte[] getData() throws IOException JavaDoc, ModuleException
472     {
473     if (!initialized) handleResponse();
474
475     if (Data == null)
476     {
477         try
478         { readResponseData(inp_stream); }
479         catch (InterruptedIOException JavaDoc ie) // don't intercept
480
{
481         throw ie;
482         }
483         catch (IOException JavaDoc ioe)
484         {
485         if (DebugResp)
486         {
487             System.err.println("HResp: (\"" + method + " " +
488                        OriginalURI.getPath() + "\")");
489             System.err.print(" ");
490             ioe.printStackTrace();
491         }
492         try { inp_stream.close(); } catch (Exception JavaDoc e) { }
493         throw ioe;
494         }
495
496         inp_stream.close();
497     }
498
499     return Data;
500     }
501
502     /**
503      * Gets an input stream from which the returned data can be read. Note
504      * that if <code>getData()</code> had been previously invoked it will
505      * actually return a ByteArrayInputStream created from that data.
506      *
507      * @see #getData()
508      * @return the InputStream.
509      * @exception IOException If any exception occurs on the socket.
510      * @exception ModuleException if any module encounters an exception.
511      */

512     public synchronized InputStream JavaDoc getInputStream()
513         throws IOException JavaDoc, ModuleException
514     {
515     if (!initialized) handleResponse();
516
517     if (Data == null)
518         return inp_stream;
519     else
520     {
521         getData(); // ensure complete data is read
522
return new ByteArrayInputStream JavaDoc(Data);
523     }
524     }
525
526
527     /**
528      * produces a full list of headers and their values, one per line.
529      *
530      * @return a string containing the headers
531      */

532     public String JavaDoc toString()
533     {
534     if (!initialized)
535     {
536         try
537         { handleResponse(); }
538         catch (Exception JavaDoc e)
539         {
540         if (DebugResp && !(e instanceof InterruptedIOException JavaDoc))
541         {
542             System.err.println("HResp: (\"" + method + " " +
543                        OriginalURI.getPath() + "\")");
544             System.err.print(" ");
545             e.printStackTrace();
546         }
547         return "Failed to read headers: " + e;
548         }
549     }
550
551     String JavaDoc nl = System.getProperty("line.separator", "\n");
552
553     StringBuffer JavaDoc str = new StringBuffer JavaDoc(Version);
554     str.append(' ');
555     str.append(StatusCode);
556     str.append(' ');
557     str.append(ReasonLine);
558     str.append(nl);
559
560     if (EffectiveURI != null)
561     {
562         str.append("Effective-URI: ");
563         str.append(EffectiveURI);
564         str.append(nl);
565     }
566
567     Enumeration JavaDoc hdr_list = Headers.keys();
568     while (hdr_list.hasMoreElements())
569     {
570         String JavaDoc hdr = (String JavaDoc) hdr_list.nextElement();
571         str.append(hdr);
572         str.append(": ");
573         str.append(Headers.get(hdr));
574         str.append(nl);
575     }
576
577     return str.toString();
578     }
579
580
581     // Helper Methods
582

583
584     HTTPClientModule[] getModules()
585     {
586     return modules;
587     }
588
589
590     /**
591      * Processes a Response. This is done by calling the response handler
592      * in each module. When all is done, the various fields of this instance
593      * are intialized from the last Response.
594      *
595      * @exception IOException if any handler throws an IOException.
596      * @exception ModuleException if any module encounters an exception.
597      * @return true if a new request was generated. This is used for internal
598      * subrequests only
599      */

600     synchronized boolean handleResponse() throws IOException JavaDoc, ModuleException
601     {
602     if (initialized) return false;
603
604
605     /* first get the response if necessary */
606
607     if (out_stream != null)
608     {
609         response = out_stream.getResponse();
610         response.http_resp = this;
611         out_stream = null;
612     }
613
614
615     /* go through modules and handle them */
616
617     doModules: while (true)
618     {
619
620     Phase1: for (int idx=0; idx<modules.length && !aborted; idx++)
621     {
622         try
623         { modules[idx].responsePhase1Handler(response, request); }
624         catch (RetryException re)
625         {
626         if (re.restart)
627             continue doModules;
628         else
629             throw re;
630         }
631     }
632
633     Phase2: for (int idx=0; idx<modules.length && !aborted; idx++)
634     {
635             int sts = modules[idx].responsePhase2Handler(response, request);
636             switch (sts)
637             {
638                 case RSP_CONTINUE: // continue processing
639
break;
640
641                 case RSP_RESTART: // restart response processing
642
idx = -1;
643             continue doModules;
644
645                 case RSP_SHORTCIRC: // stop processing and return
646
break doModules;
647
648                 case RSP_REQUEST: // go to phase 1
649
case RSP_NEWCON_REQ: // process the request using a new con
650
response.getInputStream().close();
651             if (handle_trailers) invokeTrailerHandlers(true);
652             if (request.internal_subrequest) return true;
653             request.getConnection().
654                 handleRequest(request, this, response, true);
655             if (initialized) break doModules;
656
657                     idx = -1;
658             continue doModules;
659
660                 case RSP_SEND: // send the request immediately
661
case RSP_NEWCON_SND: // send the request using a new con
662
response.getInputStream().close();
663             if (handle_trailers) invokeTrailerHandlers(true);
664             if (request.internal_subrequest) return true;
665             request.getConnection().
666                 handleRequest(request, this, response, false);
667                     idx = -1;
668             continue doModules;
669
670                 default: // not valid
671
throw new Error JavaDoc("HTTPClient Internal Error: invalid status"+
672                                     " " + sts + " returned by module " +
673                                     modules[idx].getClass().getName());
674         }
675     }
676
677     Phase3: for (int idx=0; idx<modules.length && !aborted; idx++)
678     {
679             modules[idx].responsePhase3Handler(response, request);
680     }
681
682     break doModules;
683     }
684
685     /* force a read on the response in case none of the modules did */
686     response.getStatusCode();
687
688     /* all done, so copy data */
689     if (!request.internal_subrequest)
690         init(response);
691
692     if (handle_trailers)
693         invokeTrailerHandlers(false);
694
695     return false;
696     }
697
698
699     /**
700      * Copies the relevant fields from Response and marks this as initialized.
701      *
702      * @param resp the Response class to copy from
703      */

704     void init(Response resp)
705     {
706     if (initialized) return;
707
708     this.StatusCode = resp.StatusCode;
709     this.ReasonLine = resp.ReasonLine;
710     this.Version = resp.Version;
711     this.EffectiveURI = resp.EffectiveURI;
712     this.ContentLength = resp.ContentLength;
713     this.Headers = resp.Headers;
714     this.inp_stream = resp.inp_stream;
715     this.Data = resp.Data;
716     initialized = true;
717     }
718
719
720     private boolean handle_trailers = false;
721     private boolean trailers_handled = false;
722
723     /**
724      * This is invoked by the RespInputStream when it is close()'d. It
725      * just invokes the trailer handler in each module.
726      *
727      * @param force invoke the handlers even if not initialized yet?
728      * @exception IOException if thrown by any module
729      * @exception ModuleException if thrown by any module
730      */

731     void invokeTrailerHandlers(boolean force)
732         throws IOException JavaDoc, ModuleException
733     {
734     if (trailers_handled) return;
735
736     if (!force && !initialized)
737     {
738         handle_trailers = true;
739         return;
740     }
741
742     for (int idx=0; idx<modules.length && !aborted; idx++)
743     {
744             modules[idx].trailerHandler(response, request);
745     }
746
747     trailers_handled = true;
748     }
749
750
751     /**
752      * Mark this request as having been aborted. It's invoked by
753      * HTTPConnection.stop().
754      */

755     void markAborted()
756     {
757     aborted = true;
758     }
759
760
761     /**
762      * Gets any trailers from the response if we haven't already done so.
763      */

764     private synchronized void getTrailers() throws IOException JavaDoc, ModuleException
765     {
766     if (got_trailers) return;
767     if (!initialized) handleResponse();
768
769     response.getTrailer("Any");
770     Trailers = response.Trailers;
771     got_trailers = true;
772
773     invokeTrailerHandlers(false);
774     }
775
776
777     /**
778      * Reads the response data received. Does not return until either
779      * Content-Length bytes have been read or EOF is reached.
780      *
781      * @inp the input stream from which to read the data
782      * @exception IOException if any read on the input stream fails
783      */

784     private void readResponseData(InputStream JavaDoc inp)
785         throws IOException JavaDoc, ModuleException
786     {
787     if (ContentLength == 0)
788         return;
789
790     if (Data == null)
791         Data = new byte[0];
792
793
794     // read response data
795

796     int off = Data.length;
797
798     try
799     {
800         // check Content-length header in case CE-Module removed it
801
if (getHeader("Content-Length") != null)
802         {
803         int rcvd = 0;
804         Data = new byte[ContentLength];
805
806         do
807         {
808             off += rcvd;
809             rcvd = inp.read(Data, off, ContentLength-off);
810         } while (rcvd != -1 && off+rcvd < ContentLength);
811
812                 /* Don't do this!
813          * If we do, then getData() won't work after a getInputStream()
814          * because we'll never get all the expected data. Instead, let
815          * the underlying RespInputStream throw the EOF.
816         if (rcvd == -1) // premature EOF
817         {
818             throw new EOFException("Encountered premature EOF while " +
819                         "reading headers: received " + off +
820                         " bytes instead of the expected " +
821                         ContentLength + " bytes");
822         }
823         */

824         }
825         else
826         {
827         int inc = 1000,
828             rcvd = 0;
829
830         do
831         {
832             off += rcvd;
833             Data = Util.resizeArray(Data, off+inc);
834         } while ((rcvd = inp.read(Data, off, inc)) != -1);
835
836         Data = Util.resizeArray(Data, off);
837         }
838     }
839     catch (IOException JavaDoc ioe)
840     {
841         Data = Util.resizeArray(Data, off);
842         throw ioe;
843     }
844     finally
845     {
846         try
847         { inp.close(); }
848         catch (IOException JavaDoc ioe)
849         { }
850     }
851     }
852
853
854     int getTimeout()
855     {
856     return timeout;
857     }
858 }
859
860
Popular Tags