📄 httpresponse.java
字号:
* @see #getInputStream() * @return an array containing the data (body) returned. If no data * was returned then it's set to a zero-length array. * @exception IOException If any io exception occured while reading * the data * @exception ModuleException if any module encounters an exception. */ public synchronized byte[] getData() throws IOException, ModuleException { if (!initialized) handleResponse(); if (Data == null) { try { readResponseData(inp_stream); } catch (InterruptedIOException ie) // don't intercept { throw ie; } catch (IOException ioe) { Log.write(Log.RESP, "HResp: (\"" + method + " " + OriginalURI.getPathAndQuery() + "\")"); Log.write(Log.RESP, " ", ioe); try { inp_stream.close(); } catch (Exception e) { } throw ioe; } inp_stream.close(); } return Data; } /** * Gets an input stream from which the returned data can be read. Note * that if <code>getData()</code> had been previously invoked it will * actually return a ByteArrayInputStream created from that data. * * @see #getData() * @return the InputStream. * @exception IOException If any exception occurs on the socket. * @exception ModuleException if any module encounters an exception. */ public synchronized InputStream getInputStream() throws IOException, ModuleException { if (!initialized) handleResponse(); if (Data == null) return inp_stream; else { getData(); // ensure complete data is read return new ByteArrayInputStream(Data); } } /** * Should the request be retried by the application? If the application * used an <var>HttpOutputStream</var> in the request then various * modules (such as the redirection and authorization modules) are not * able to resend the request themselves. Instead, it becomes the * application's responsibility. * * <P>If the application resends the request then it <strong>must</strong> * use the same <var>HttpOutputStream</var> instance. This is because the * modules use this to recognize the retried request and to perform the * necessary work on the request before it's sent. * * <P>Here is a skeleton example of usage: * <PRE> * OutputStream out = new HttpOutputStream(1234); * do * { * rsp = con.Post("/cgi-bin/my_cgi", out); * out.write(...); * out.close(); * } while (rsp.retryRequest()); * * if (rsp.getStatusCode() >= 300) * ... * </PRE> * * @return true if the request should be retried. * @exception IOException If any exception occurs on the socket. * @exception ModuleException if any module encounters an exception. */ public boolean retryRequest() throws IOException, ModuleException { if (!initialized) { try { handleResponse(); } catch (RetryException re) { this.retry = response.retry; } } return retry; } /** * produces a full list of headers and their values, one per line. * * @return a string containing the headers */ public String toString() { if (!initialized) { try { handleResponse(); } catch (Exception e) { if (!(e instanceof InterruptedIOException)) { Log.write(Log.RESP, "HResp: (\"" + method + " " + OriginalURI.getPathAndQuery() + "\")"); Log.write(Log.RESP, " ", e); } return "Failed to read headers: " + e; } } String nl = System.getProperty("line.separator", "\n"); StringBuffer str = new StringBuffer(Version); str.append(' '); str.append(StatusCode); str.append(' '); str.append(ReasonLine); str.append(nl); if (EffectiveURI != null) { str.append("Effective-URI: "); str.append(EffectiveURI); str.append(nl); } Enumeration hdr_list = Headers.keys(); while (hdr_list.hasMoreElements()) { String hdr = (String) hdr_list.nextElement(); str.append(hdr); str.append(": "); str.append(Headers.get(hdr)); str.append(nl); } return str.toString(); } // Helper Methods HTTPClientModule[] getModules() { return modules; } /** * Processes a Response. This is done by calling the response handler * in each module. When all is done, the various fields of this instance * are intialized from the last Response. * * @exception IOException if any handler throws an IOException. * @exception ModuleException if any module encounters an exception. * @return true if a new request was generated. This is used for internal * subrequests only */ synchronized boolean handleResponse() throws IOException, ModuleException { if (initialized) return false; /* first get the response if necessary */ if (out_stream != null) { response = out_stream.getResponse(); response.http_resp = this; out_stream = null; } /* go through modules and handle them */ doModules: while (true) { Phase1: for (int idx=0; idx<modules.length && !aborted; idx++) { try { modules[idx].responsePhase1Handler(response, request); } catch (RetryException re) { if (re.restart) continue doModules; else throw re; } } Phase2: for (int idx=0; idx<modules.length && !aborted; idx++) { int sts = modules[idx].responsePhase2Handler(response, request); switch (sts) { case RSP_CONTINUE: // continue processing break; case RSP_RESTART: // restart response processing idx = -1; continue doModules; case RSP_SHORTCIRC: // stop processing and return break doModules; case RSP_REQUEST: // go to phase 1 case RSP_NEWCON_REQ: // process the request using a new con response.getInputStream().close(); if (handle_trailers) invokeTrailerHandlers(true); if (request.internal_subrequest) return true; request.getConnection(). handleRequest(request, this, response, true); if (initialized) break doModules; idx = -1; continue doModules; case RSP_SEND: // send the request immediately case RSP_NEWCON_SND: // send the request using a new con response.getInputStream().close(); if (handle_trailers) invokeTrailerHandlers(true); if (request.internal_subrequest) return true; request.getConnection(). handleRequest(request, this, response, false); idx = -1; continue doModules; default: // not valid throw new Error("HTTPClient Internal Error: invalid status"+ " " + sts + " returned by module " + modules[idx].getClass().getName()); } } Phase3: for (int idx=0; idx<modules.length && !aborted; idx++) { modules[idx].responsePhase3Handler(response, request); } break doModules; } /* force a read on the response in case none of the modules did */ response.getStatusCode(); /* all done, so copy data */ if (!request.internal_subrequest) init(response); if (handle_trailers) invokeTrailerHandlers(false); return false; } /** * Copies the relevant fields from Response and marks this as initialized. * * @param resp the Response class to copy from */ void init(Response resp) { if (initialized) return; this.StatusCode = resp.StatusCode; this.ReasonLine = resp.ReasonLine; this.Version = resp.Version; this.EffectiveURI = resp.EffectiveURI; this.ContentLength = resp.ContentLength; this.Headers = resp.Headers; this.inp_stream = resp.inp_stream; this.Data = resp.Data; this.retry = resp.retry; initialized = true; // for HotJava (or anybody else) try { if (pe != null && ContentLength != -1) { pe.setType(Util.getPath(request.getRequestURI()), getHeader("Content-type")); sun.net.ProgressData.pdata.register(pe); pe.update(0, ContentLength); } } catch (Throwable t) { Log.write(Log.RESP, "Resp: ", t); } } private boolean handle_trailers = false; private boolean trailers_handled = false; /** * This is invoked by the RespInputStream when it is close()'d. It * just invokes the trailer handler in each module. * * @param force invoke the handlers even if not initialized yet? * @exception IOException if thrown by any module * @exception ModuleException if thrown by any module */ void invokeTrailerHandlers(boolean force) throws IOException, ModuleException { if (trailers_handled) return; if (!force && !initialized) { handle_trailers = true; return; } for (int idx=0; idx<modules.length && !aborted; idx++) { modules[idx].trailerHandler(response, request); } trailers_handled = true; } ProgressEntry pe = null; /** * The ProgressEntry is used by HotJava to monitor the loading progress. * HttpURLConnection sets this. * * @param pe a ProgressEntry */ void setProgressEntry(ProgressEntry pe) { this.pe = pe; } /** * Unset and unregister any ProgressEntry. * * @see #setProgressEntry(sun.net.ProgressEntry) */ void unsetProgressEntry() { if (pe != null) { try { sun.net.ProgressData.pdata.unregister(pe); } catch (Throwable t) { } pe = null; } } /** * Mark this request as having been aborted. It's invoked by * HTTPConnection.stop(). */ void markAborted() { aborted = true; } /** * Gets any trailers from the response if we haven't already done so. */ private synchronized void getTrailers() throws IOException, ModuleException { if (got_trailers) return; if (!initialized) handleResponse(); response.getTrailer("Any"); Trailers = response.Trailers; got_trailers = true; invokeTrailerHandlers(false); } /** * Reads the response data received. Does not return until either * Content-Length bytes have been read or EOF is reached. * * @inp the input stream from which to read the data * @exception IOException if any read on the input stream fails */ private void readResponseData(InputStream inp) throws IOException, ModuleException { if (ContentLength == 0) return; if (Data == null) Data = new byte[0]; // read response data int off = Data.length; try { // check Content-length header in case CE-Module removed it if (getHeader("Content-Length") != null) { int rcvd = 0; Data = new byte[ContentLength]; do { off += rcvd; rcvd = inp.read(Data, off, ContentLength-off); } while (rcvd != -1 && off+rcvd < ContentLength); /* Don't do this! * If we do, then getData() won't work after a getInputStream() * because we'll never get all the expected data. Instead, let * the underlying RespInputStream throw the EOF. if (rcvd == -1) // premature EOF { throw new EOFException("Encountered premature EOF while " + "reading headers: received " + off + " bytes instead of the expected " + ContentLength + " bytes"); } */ } else { int inc = 1000, rcvd = 0; do { off += rcvd; Data = Util.resizeArray(Data, off+inc); } while ((rcvd = inp.read(Data, off, inc)) != -1); Data = Util.resizeArray(Data, off); } } catch (IOException ioe) { Data = Util.resizeArray(Data, off); throw ioe; } finally { try { inp.close(); } catch (IOException ioe) { } } } int getTimeout() { return timeout; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -