HTTPResponse.java
Upload User: demmber
Upload Date: 2007-12-22
Package Size: 717k
Code Size: 27k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * @(#)HTTPResponse.java 0.3-3 18/06/1999
  3.  *
  4.  *  This file is part of the HTTPClient package
  5.  *  Copyright (C) 1996-2001 Ronald Tschal鋜
  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.  *  The HTTPClient's home page is located at:
  28.  *
  29.  *  http://www.innovation.ch/java/HTTPClient/ 
  30.  *
  31.  */
  32. package HTTPClient;
  33. import java.io.IOException;
  34. import java.io.InterruptedIOException;
  35. import java.io.InputStream;
  36. import java.io.ByteArrayInputStream;
  37. import java.net.URL;
  38. import java.util.Date;
  39. import java.util.Enumeration;
  40. import sun.net.ProgressEntry;
  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-3  18/06/1999
  48.  * @author Ronald Tschal鋜
  49.  * @since 0.3
  50.  */
  51. public class HTTPResponse implements GlobalConstants, HTTPClientModuleConstants
  52. {
  53.     /** the list of modules */
  54.     private HTTPClientModule[]  modules;
  55.     /** the timeout for reads */
  56.     private int          timeout;
  57.     /** the request */
  58.     private Request      request = null;
  59.     /** the current response */
  60.             Response     response = null;
  61.     /** the HttpOutputStream to synchronize on */
  62.     private HttpOutputStream out_stream = null;
  63.     /** our input stream from the stream demux */
  64.     private InputStream  inp_stream;
  65.     /** the status code returned. */
  66.     private int          StatusCode;
  67.     /** the reason line associated with the status code. */
  68.     private String       ReasonLine;
  69.     /** the HTTP version of the response. */
  70.     private String       Version;
  71.     /** the original URI used. */
  72.     private URI          OriginalURI = null;
  73.     /** the final URI of the document. */
  74.     private URI          EffectiveURI = null;
  75.     /** any headers which were received and do not fit in the above list. */
  76.     private CIHashtable  Headers = null;
  77.     /** any trailers which were received and do not fit in the above list. */
  78.     private CIHashtable  Trailers = null;
  79.     /** the ContentLength of the data. */
  80.     private int          ContentLength = -1;
  81.     /** the data (body) returned. */
  82.     private byte[]       Data = null;
  83.     /** signals if we have got and parsed the headers yet? */
  84.     private boolean      initialized = false;
  85.     /** signals if we have got the trailers yet? */
  86.     private boolean      got_trailers = false;
  87.     /** marks this response as aborted (stop() in HTTPConnection) */
  88.     private boolean      aborted = false;
  89.     /** should the request be retried by the application? */
  90.     private boolean      retry = false;
  91.     /** the method used in the request */
  92.     private String       method = null;
  93.     // Constructors
  94.     /**
  95.      * Creates a new HTTPResponse.
  96.      *
  97.      * @param modules the list of modules handling this response
  98.      * @param timeout the timeout to be used on stream read()'s
  99.      */
  100.     HTTPResponse(HTTPClientModule[] modules, int timeout, Request orig)
  101.     {
  102. this.modules = modules;
  103. this.timeout = timeout;
  104. try
  105. {
  106.     int qp = orig.getRequestURI().indexOf('?');
  107.     this.OriginalURI = new URI(orig.getConnection().getProtocol(),
  108.        null,
  109.        orig.getConnection().getHost(),
  110.        orig.getConnection().getPort(),
  111.        qp < 0 ? orig.getRequestURI() :
  112.  orig.getRequestURI().substring(0, qp),
  113.        qp < 0 ? null :
  114.  orig.getRequestURI().substring(qp+1),
  115.        null);
  116. }
  117. catch (ParseException pe)
  118.     { }
  119. this.method = orig.getMethod();
  120.     }
  121.     /**
  122.      * @param req the request
  123.      * @param resp the response
  124.      */
  125.     void set(Request req, Response resp)
  126.     {
  127. this.request   = req;
  128. this.response  = resp;
  129. resp.http_resp = this;
  130. resp.timeout   = timeout;
  131. this.aborted   = resp.final_resp;
  132.     }
  133.     /**
  134.      * @param req the request
  135.      * @param resp the response
  136.      */
  137.     void set(Request req, HttpOutputStream out_stream)
  138.     {
  139. this.request    = req;
  140. this.out_stream = out_stream;
  141.     }
  142.     // Methods
  143.     /**
  144.      * Give the status code for this request. These are grouped as follows:
  145.      * <UL>
  146.      *   <LI> 1xx - Informational (new in HTTP/1.1)
  147.      *   <LI> 2xx - Success
  148.      *   <LI> 3xx - Redirection
  149.      *   <LI> 4xx - Client Error
  150.      *   <LI> 5xx - Server Error
  151.      * </UL>
  152.      *
  153.      * @exception IOException if any exception occurs on the socket.
  154.      * @exception ModuleException if any module encounters an exception.
  155.      */
  156.     public final int getStatusCode()  throws IOException, ModuleException
  157.     {
  158. if (!initialized)  handleResponse();
  159. return StatusCode;
  160.     }
  161.     /**
  162.      * Give the reason line associated with the status code.
  163.      *
  164.      * @exception IOException If any exception occurs on the socket.
  165.      * @exception ModuleException if any module encounters an exception.
  166.      */
  167.     public final String getReasonLine()  throws IOException, ModuleException
  168.     {
  169. if (!initialized)  handleResponse();
  170. return ReasonLine;
  171.     }
  172.     /**
  173.      * Get the HTTP version used for the response.
  174.      *
  175.      * @exception IOException If any exception occurs on the socket.
  176.      * @exception ModuleException if any module encounters an exception.
  177.      */
  178.     public final String getVersion()  throws IOException, ModuleException
  179.     {
  180. if (!initialized)  handleResponse();
  181. return Version;
  182.     }
  183.     /**
  184.      * Get the name and type of server.
  185.      *
  186.      * @deprecated This method is a remnant of V0.1; use
  187.      *             <code>getHeader("Server")</code> instead.
  188.      * @see #getHeader(java.lang.String)
  189.      * @exception IOException If any exception occurs on the socket.
  190.      * @exception ModuleException if any module encounters an exception.
  191.      */
  192.     public final String getServer()  throws IOException, ModuleException
  193.     {
  194. if (!initialized)  handleResponse();
  195. return getHeader("Server");
  196.     }
  197.     /**
  198.      * Get the original URI used in the request.
  199.      *
  200.      * @return the URI used in primary request
  201.      */
  202.     public final URI getOriginalURI()
  203.     {
  204. return OriginalURI;
  205.     }
  206.     /**
  207.      * Get the final URL of the document. This is set if the original
  208.      * request was deferred via the "moved" (301, 302, or 303) return
  209.      * status.
  210.      *
  211.      * @return the effective URL, or null if no redirection occured
  212.      * @exception IOException If any exception occurs on the socket.
  213.      * @exception ModuleException if any module encounters an exception.
  214.      * @deprecated use getEffectiveURI() instead
  215.      * @see #getEffectiveURI
  216.      */
  217.     public final URL getEffectiveURL()  throws IOException, ModuleException
  218.     {
  219. if (!initialized)  handleResponse();
  220. if (EffectiveURI != null)
  221.     return EffectiveURI.toURL();
  222. return null;
  223.     }
  224.     /**
  225.      * Get the final URI of the document. If the request was redirected
  226.      * via the "moved" (301, 302, 303, or 307) return status this returns
  227.      * the URI used in the last redirection; otherwise it returns the
  228.      * original URI.
  229.      *
  230.      * @return the effective URI
  231.      * @exception IOException If any exception occurs on the socket.
  232.      * @exception ModuleException if any module encounters an exception.
  233.      */
  234.     public final URI getEffectiveURI()  throws IOException, ModuleException
  235.     {
  236. if (!initialized)  handleResponse();
  237. if (EffectiveURI != null)
  238.     return EffectiveURI;
  239. return OriginalURI;
  240.     }
  241.     /**
  242.      * Retrieves the value for a given header.
  243.      *
  244.      * @param  hdr the header name.
  245.      * @return the value for the header, or null if non-existent.
  246.      * @exception IOException If any exception occurs on the socket.
  247.      * @exception ModuleException if any module encounters an exception.
  248.      */
  249.     public String getHeader(String hdr)  throws IOException, ModuleException
  250.     {
  251. if (!initialized)  handleResponse();
  252. return (String) Headers.get(hdr.trim());
  253.     }
  254.     /**
  255.      * Retrieves the value for a given header. The value is parsed as an
  256.      * int.
  257.      *
  258.      * @param  hdr the header name.
  259.      * @return the value for the header if the header exists
  260.      * @exception NumberFormatException if the header's value is not a number
  261.      *                                  or if the header does not exist.
  262.      * @exception IOException if any exception occurs on the socket.
  263.      * @exception ModuleException if any module encounters an exception.
  264.      */
  265.     public int getHeaderAsInt(String hdr)
  266. throws IOException, ModuleException, NumberFormatException
  267.     {
  268. String val = getHeader(hdr);
  269. if (val == null)
  270.     throw new NumberFormatException("null");
  271. return Integer.parseInt(val);
  272.     }
  273.     /**
  274.      * Retrieves the value for a given header. The value is parsed as a
  275.      * date; if this fails it is parsed as a long representing the number
  276.      * of seconds since 12:00 AM, Jan 1st, 1970. If this also fails an
  277.      * exception is thrown.
  278.      * <br>Note: When sending dates use Util.httpDate().
  279.      *
  280.      * @param  hdr the header name.
  281.      * @return the value for the header, or null if non-existent.
  282.      * @exception IllegalArgumentException if the header's value is neither a
  283.      *            legal date nor a number.
  284.      * @exception IOException if any exception occurs on the socket.
  285.      * @exception ModuleException if any module encounters an exception.
  286.      */
  287.     public Date getHeaderAsDate(String hdr)
  288. throws IOException, IllegalArgumentException, ModuleException
  289.     {
  290. String raw_date = getHeader(hdr);
  291. if (raw_date == null) return null;
  292. // asctime() format is missing an explicit GMT specifier
  293. if (raw_date.toUpperCase().indexOf("GMT") == -1  &&
  294.     raw_date.indexOf(' ') > 0)
  295.     raw_date += " GMT";
  296. Date   date;
  297. try
  298.     { date = Util.parseHttpDate(raw_date); }
  299. catch (IllegalArgumentException iae)
  300. {
  301.     // some servers erroneously send a number, so let's try that
  302.     long time;
  303.     try
  304. { time = Long.parseLong(raw_date); }
  305.     catch (NumberFormatException nfe)
  306. { throw iae; } // give up
  307.     if (time < 0)  time = 0;
  308.     date = new Date(time * 1000L);
  309. }
  310. return date;
  311.     }
  312.     /**
  313.      * Returns an enumeration of all the headers available via getHeader().
  314.      *
  315.      * @exception IOException If any exception occurs on the socket.
  316.      * @exception ModuleException if any module encounters an exception.
  317.      */
  318.     public Enumeration listHeaders()  throws IOException, ModuleException
  319.     {
  320. if (!initialized)  handleResponse();
  321. return Headers.keys();
  322.     }
  323.     /**
  324.      * Retrieves the value for a given trailer. This should not be invoked
  325.      * until all response data has been read. If invoked before it will
  326.      * call <code>getData()</code> to force the data to be read.
  327.      *
  328.      * @param  trailer the trailer name.
  329.      * @return the value for the trailer, or null if non-existent.
  330.      * @exception IOException If any exception occurs on the socket.
  331.      * @exception ModuleException if any module encounters an exception.
  332.      * @see #getData()
  333.      */
  334.     public String getTrailer(String trailer) throws IOException, ModuleException
  335.     {
  336. if (!got_trailers)  getTrailers();
  337. return (String) Trailers.get(trailer.trim());
  338.     }
  339.     /**
  340.      * Retrieves the value for a given tailer. The value is parsed as an
  341.      * int.
  342.      *
  343.      * @param  trailer the tailer name.
  344.      * @return the value for the trailer if the trailer exists
  345.      * @exception NumberFormatException if the trailer's value is not a number
  346.      *                                  or if the trailer does not exist.
  347.      * @exception IOException if any exception occurs on the socket.
  348.      * @exception ModuleException if any module encounters an exception.
  349.      */
  350.     public int getTrailerAsInt(String trailer)
  351. throws IOException, ModuleException, NumberFormatException
  352.     {
  353. String val = getTrailer(trailer);
  354. if (val == null)
  355.     throw new NumberFormatException("null");
  356. return Integer.parseInt(val);
  357.     }
  358.     /**
  359.      * Retrieves the value for a given trailer. The value is parsed as a
  360.      * date; if this fails it is parsed as a long representing the number
  361.      * of seconds since 12:00 AM, Jan 1st, 1970. If this also fails an
  362.      * IllegalArgumentException is thrown.
  363.      * <br>Note: When sending dates use Util.httpDate().
  364.      *
  365.      * @param  trailer the trailer name.
  366.      * @return the value for the trailer, or null if non-existent.
  367.      * @exception IllegalArgumentException if the trailer's value is neither a
  368.      *            legal date nor a number.
  369.      * @exception IOException if any exception occurs on the socket.
  370.      * @exception ModuleException if any module encounters an exception.
  371.      */
  372.     public Date getTrailerAsDate(String trailer)
  373. throws IOException, IllegalArgumentException, ModuleException
  374.     {
  375. String raw_date = getTrailer(trailer);
  376. if (raw_date == null) return null;
  377. // asctime() format is missing an explicit GMT specifier
  378. if (raw_date.toUpperCase().indexOf("GMT") == -1  &&
  379.     raw_date.indexOf(' ') > 0)
  380.     raw_date += " GMT";
  381. Date   date;
  382. try
  383.     { date = Util.parseHttpDate(raw_date); }
  384. catch (IllegalArgumentException iae)
  385. {
  386.     // some servers erroneously send a number, so let's try that
  387.     long time;
  388.     try
  389. { time = Long.parseLong(raw_date); }
  390.     catch (NumberFormatException nfe)
  391. { throw iae; } // give up
  392.     if (time < 0)  time = 0;
  393.     date = new Date(time * 1000L);
  394. }
  395. return date;
  396.     }
  397.     /**
  398.      * Returns an enumeration of all the trailers available via getTrailer().
  399.      *
  400.      * @exception IOException If any exception occurs on the socket.
  401.      * @exception ModuleException if any module encounters an exception.
  402.      */
  403.     public Enumeration listTrailers()  throws IOException, ModuleException
  404.     {
  405. if (!got_trailers)  getTrailers();
  406. return Trailers.keys();
  407.     }
  408.     /**
  409.      * Reads all the response data into a byte array. Note that this method
  410.      * won't return until <em>all</em> the data has been received (so for
  411.      * instance don't invoke this method if the server is doing a server
  412.      * push). If <code>getInputStream()</code> had been previously invoked
  413.      * then this method only returns any unread data remaining on the stream
  414.      * and then closes it.
  415.      *
  416.      * <P>Note to the unwarry: code like
  417.      *    <code>System.out.println("The data: " + resp.getData())</code>
  418.      * will probably not do what you want - use
  419.      *    <code>System.out.println("The data: " + new String(resp.getData()))</code>
  420.      * instead.
  421.      *
  422.      * @see #getInputStream()
  423.      * @return an array containing the data (body) returned. If no data
  424.      *         was returned then it's set to a zero-length array.
  425.      * @exception IOException If any io exception occured while reading
  426.      *       the data
  427.      * @exception ModuleException if any module encounters an exception.
  428.      */
  429.     public synchronized byte[] getData()  throws IOException, ModuleException
  430.     {
  431. if (!initialized)  handleResponse();
  432. if (Data == null)
  433. {
  434.     try
  435. { readResponseData(inp_stream); }
  436.     catch (InterruptedIOException ie) // don't intercept
  437.     {
  438. throw ie;
  439.     }
  440.     catch (IOException ioe)
  441.     {
  442. Log.write(Log.RESP, "HResp: ("" + method + " " +
  443.     OriginalURI.getPathAndQuery() + "")");
  444. Log.write(Log.RESP, "       ", ioe);
  445. try { inp_stream.close(); } catch (Exception e) { }
  446. throw ioe;
  447.     }
  448.     inp_stream.close();
  449. }
  450. return Data;
  451.     }
  452.     /**
  453.      * Gets an input stream from which the returned data can be read. Note
  454.      * that if <code>getData()</code> had been previously invoked it will
  455.      * actually return a ByteArrayInputStream created from that data.
  456.      *
  457.      * @see #getData()
  458.      * @return the InputStream.
  459.      * @exception IOException If any exception occurs on the socket.
  460.      * @exception ModuleException if any module encounters an exception.
  461.      */
  462.     public synchronized InputStream getInputStream()
  463.     throws IOException, ModuleException
  464.     {
  465. if (!initialized)  handleResponse();
  466. if (Data == null)
  467.     return inp_stream;
  468. else
  469. {
  470.     getData(); // ensure complete data is read
  471.     return new ByteArrayInputStream(Data);
  472. }
  473.     }
  474.     /**
  475.      * Should the request be retried by the application? If the application
  476.      * used an <var>HttpOutputStream</var> in the request then various
  477.      * modules (such as the redirection and authorization modules) are not
  478.      * able to resend the request themselves. Instead, it becomes the
  479.      * application's responsibility.
  480.      *
  481.      * <P>If the application resends the request then it <strong>must</strong>
  482.      * use the same <var>HttpOutputStream</var> instance. This is because the
  483.      * modules use this to recognize the retried request and to perform the
  484.      * necessary work on the request before it's sent.
  485.      *
  486.      * <P>Here is a skeleton example of usage:
  487.      * <PRE>
  488.      *     OutputStream out = new HttpOutputStream(1234);
  489.      *     do
  490.      *     {
  491.      *         rsp = con.Post("/cgi-bin/my_cgi", out);
  492.      *         out.write(...);
  493.      *         out.close();
  494.      *     } while (rsp.retryRequest());
  495.      *
  496.      *     if (rsp.getStatusCode() >= 300)
  497.      *         ...
  498.      * </PRE>
  499.      *
  500.      * @return true if the request should be retried.
  501.      * @exception IOException If any exception occurs on the socket.
  502.      * @exception ModuleException if any module encounters an exception.
  503.      */
  504.     public boolean retryRequest()  throws IOException, ModuleException
  505.     {
  506. if (!initialized)
  507. {
  508.     try
  509. { handleResponse(); }
  510.     catch (RetryException re)
  511. { this.retry = response.retry; }
  512. }
  513. return retry;
  514.     }
  515.     /**
  516.      * produces a full list of headers and their values, one per line.
  517.      *
  518.      * @return a string containing the headers
  519.      */
  520.     public String toString()
  521.     {
  522. if (!initialized)
  523. {
  524.     try
  525. { handleResponse(); }
  526.     catch (Exception e)
  527.     {
  528. if (!(e instanceof InterruptedIOException))
  529. {
  530.     Log.write(Log.RESP, "HResp: ("" + method + " " +
  531.         OriginalURI.getPathAndQuery() + "")");
  532.     Log.write(Log.RESP, "       ", e);
  533. }
  534. return "Failed to read headers: " + e;
  535.     }
  536. }
  537. String nl = System.getProperty("line.separator", "n");
  538. StringBuffer str = new StringBuffer(Version);
  539. str.append(' ');
  540. str.append(StatusCode);
  541. str.append(' ');
  542. str.append(ReasonLine);
  543. str.append(nl);
  544. if (EffectiveURI != null)
  545. {
  546.     str.append("Effective-URI: ");
  547.     str.append(EffectiveURI);
  548.     str.append(nl);
  549. }
  550. Enumeration hdr_list = Headers.keys();
  551. while (hdr_list.hasMoreElements())
  552. {
  553.     String hdr = (String) hdr_list.nextElement();
  554.     str.append(hdr);
  555.     str.append(": ");
  556.     str.append(Headers.get(hdr));
  557.     str.append(nl);
  558. }
  559. return str.toString();
  560.     }
  561.     // Helper Methods
  562.     HTTPClientModule[] getModules()
  563.     {
  564. return modules;
  565.     }
  566.     /**
  567.      * Processes a Response. This is done by calling the response handler
  568.      * in each module. When all is done, the various fields of this instance
  569.      * are intialized from the last Response.
  570.      *
  571.      * @exception IOException if any handler throws an IOException.
  572.      * @exception ModuleException if any module encounters an exception.
  573.      * @return true if a new request was generated. This is used for internal
  574.      *         subrequests only
  575.      */
  576.     synchronized boolean handleResponse()  throws IOException, ModuleException
  577.     {
  578. if (initialized)  return false;
  579. /* first get the response if necessary */
  580. if (out_stream != null)
  581. {
  582.     response           = out_stream.getResponse();
  583.     response.http_resp = this;
  584.     out_stream         = null;
  585. }
  586. /* go through modules and handle them */
  587. doModules: while (true)
  588. {
  589. Phase1: for (int idx=0; idx<modules.length && !aborted; idx++)
  590. {
  591.     try
  592. { modules[idx].responsePhase1Handler(response, request); }
  593.     catch (RetryException re)
  594.     {
  595. if (re.restart)
  596.     continue doModules;
  597. else
  598.     throw re;
  599.     }
  600. }
  601. Phase2: for (int idx=0; idx<modules.length && !aborted; idx++)
  602. {
  603.             int sts = modules[idx].responsePhase2Handler(response, request);
  604.             switch (sts)
  605.             {
  606.                 case RSP_CONTINUE: // continue processing
  607.                     break;
  608.                 case RSP_RESTART: // restart response processing
  609.                     idx = -1;
  610.     continue doModules;
  611.                 case RSP_SHORTCIRC: // stop processing and return
  612.                     break doModules;
  613.                 case RSP_REQUEST: // go to phase 1
  614.                 case RSP_NEWCON_REQ: // process the request using a new con
  615.     response.getInputStream().close();
  616.     if (handle_trailers) invokeTrailerHandlers(true);
  617.     if (request.internal_subrequest)  return true;
  618.     request.getConnection().
  619. handleRequest(request, this, response, true);
  620.     if (initialized)  break doModules;
  621.                     idx = -1;
  622.     continue doModules;
  623.                 case RSP_SEND: // send the request immediately
  624.                 case RSP_NEWCON_SND: // send the request using a new con
  625.     response.getInputStream().close();
  626.     if (handle_trailers) invokeTrailerHandlers(true);
  627.     if (request.internal_subrequest)  return true;
  628.     request.getConnection().
  629. handleRequest(request, this, response, false);
  630.                     idx = -1;
  631.     continue doModules;
  632.                 default:                // not valid
  633.                     throw new Error("HTTPClient Internal Error: invalid status"+
  634.                                     " " + sts + " returned by module " +
  635.                                     modules[idx].getClass().getName());
  636.     }
  637. }
  638. Phase3: for (int idx=0; idx<modules.length && !aborted; idx++)
  639. {
  640.             modules[idx].responsePhase3Handler(response, request);
  641. }
  642. break doModules;
  643. }
  644. /* force a read on the response in case none of the modules did */
  645. response.getStatusCode();
  646. /* all done, so copy data */
  647. if (!request.internal_subrequest)
  648.     init(response);
  649. if (handle_trailers)
  650.     invokeTrailerHandlers(false);
  651. return false;
  652.     }
  653.     /**
  654.      * Copies the relevant fields from Response and marks this as initialized.
  655.      *
  656.      * @param resp the Response class to copy from
  657.      */
  658.     void init(Response resp)
  659.     {
  660. if (initialized)  return;
  661. this.StatusCode    = resp.StatusCode;
  662. this.ReasonLine    = resp.ReasonLine;
  663. this.Version       = resp.Version;
  664. this.EffectiveURI  = resp.EffectiveURI;
  665. this.ContentLength = resp.ContentLength;
  666. this.Headers       = resp.Headers;
  667. this.inp_stream    = resp.inp_stream;
  668. this.Data          = resp.Data;
  669. this.retry         = resp.retry;
  670. initialized        = true;
  671. // for HotJava (or anybody else)
  672. try
  673. {
  674.     if (pe != null  &&  ContentLength != -1)
  675.     {
  676. pe.setType(Util.getPath(request.getRequestURI()),
  677.    getHeader("Content-type"));
  678. sun.net.ProgressData.pdata.register(pe);
  679. pe.update(0, ContentLength);
  680.     }
  681. }
  682. catch (Throwable t)
  683. {
  684.     Log.write(Log.RESP, "Resp: ", t);
  685. }
  686.     }
  687.     private boolean handle_trailers  = false;
  688.     private boolean trailers_handled = false;
  689.     /**
  690.      * This is invoked by the RespInputStream when it is close()'d. It
  691.      * just invokes the trailer handler in each module.
  692.      *
  693.      * @param force invoke the handlers even if not initialized yet?
  694.      * @exception IOException     if thrown by any module
  695.      * @exception ModuleException if thrown by any module
  696.      */
  697.     void invokeTrailerHandlers(boolean force)
  698.     throws IOException, ModuleException
  699.     {
  700. if (trailers_handled)  return;
  701. if (!force  &&  !initialized)
  702. {
  703.     handle_trailers = true;
  704.     return;
  705. }
  706. for (int idx=0; idx<modules.length && !aborted; idx++)
  707. {
  708.             modules[idx].trailerHandler(response, request);
  709. }
  710. trailers_handled = true;
  711.     }
  712.     ProgressEntry pe = null;
  713.     /**
  714.      * The ProgressEntry is used by HotJava to monitor the loading progress.
  715.      * HttpURLConnection sets this.
  716.      *
  717.      * @param pe a ProgressEntry
  718.      */
  719.     void setProgressEntry(ProgressEntry pe)
  720.     {
  721. this.pe = pe;
  722.     }
  723.     /**
  724.      * Unset and unregister any ProgressEntry.
  725.      *
  726.      * @see #setProgressEntry(sun.net.ProgressEntry)
  727.      */
  728.     void unsetProgressEntry()
  729.     {
  730. if (pe != null)
  731. {
  732.     try
  733. { sun.net.ProgressData.pdata.unregister(pe); }
  734.     catch (Throwable t)
  735. { }
  736.     pe = null;
  737. }
  738.     }
  739.     /**
  740.      * Mark this request as having been aborted. It's invoked by
  741.      * HTTPConnection.stop().
  742.      */
  743.     void markAborted()
  744.     {
  745. aborted = true;
  746.     }
  747.     /**
  748.      * Gets any trailers from the response if we haven't already done so.
  749.      */
  750.     private synchronized void getTrailers()  throws IOException, ModuleException
  751.     {
  752. if (got_trailers)  return;
  753. if (!initialized)  handleResponse();
  754. response.getTrailer("Any");
  755. Trailers = response.Trailers;
  756. got_trailers = true;
  757. invokeTrailerHandlers(false);
  758.     }
  759.     /**
  760.      * Reads the response data received. Does not return until either
  761.      * Content-Length bytes have been read or EOF is reached.
  762.      *
  763.      * @inp       the input stream from which to read the data
  764.      * @exception IOException if any read on the input stream fails
  765.      */
  766.     private void readResponseData(InputStream inp)
  767.     throws IOException, ModuleException
  768.     {
  769. if (ContentLength == 0)
  770.     return;
  771. if (Data == null)
  772.     Data = new byte[0];
  773. // read response data
  774. int off = Data.length;
  775. try
  776. {
  777.     // check Content-length header in case CE-Module removed it
  778.     if (getHeader("Content-Length") != null)
  779.     {
  780. int rcvd = 0;
  781. Data = new byte[ContentLength];
  782. do
  783. {
  784.     off  += rcvd;
  785.     rcvd  = inp.read(Data, off, ContentLength-off);
  786. } while (rcvd != -1  &&  off+rcvd < ContentLength);
  787.                 /* Don't do this!
  788.  * If we do, then getData() won't work after a getInputStream()
  789.  * because we'll never get all the expected data. Instead, let
  790.  * the underlying RespInputStream throw the EOF.
  791. if (rcvd == -1) // premature EOF
  792. {
  793.     throw new EOFException("Encountered premature EOF while " +
  794.     "reading headers: received " + off +
  795.     " bytes instead of the expected " +
  796.     ContentLength + " bytes");
  797. }
  798. */
  799.     }
  800.     else
  801.     {
  802. int inc  = 1000,
  803.     rcvd = 0;
  804. do
  805. {
  806.     off  += rcvd;
  807.     Data  = Util.resizeArray(Data, off+inc);
  808. } while ((rcvd = inp.read(Data, off, inc)) != -1);
  809. Data = Util.resizeArray(Data, off);
  810.     }
  811. }
  812. catch (IOException ioe)
  813. {
  814.     Data = Util.resizeArray(Data, off);
  815.     throw ioe;
  816. }
  817. finally
  818. {
  819.     try
  820. { inp.close(); }
  821.     catch (IOException ioe)
  822. { }
  823. }
  824.     }
  825.     int getTimeout()
  826.     {
  827. return timeout;
  828.     }
  829. }