📄 reply.java
字号:
// Reply.java// $Id: Reply.java,v 1.38 2003/02/25 17:52:01 ylafon Exp $// (c) COPYRIGHT MIT and INRIA, 1996.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.jigsaw.http ;import java.io.ByteArrayInputStream;import java.io.DataOutputStream;import java.io.FileDescriptor;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import org.w3c.www.mime.MimeType;import org.w3c.www.http.HTTP;import org.w3c.www.http.HeaderValue;import org.w3c.www.http.HttpEntityMessage;import org.w3c.www.http.HttpFactory;import org.w3c.www.http.HttpMessage;import org.w3c.www.http.HttpMimeType;import org.w3c.www.http.HttpReplyMessage;import org.w3c.www.http.HttpRequestMessage;import org.w3c.www.http.HttpTokenList;import org.w3c.tools.resources.ReplyInterface;import org.w3c.tools.resources.RequestInterface;import org.w3c.tools.resources.ResourceFilter;public class Reply extends HttpReplyMessage implements ReplyInterface { protected static HttpMimeType DEFAULT_TYPE = null; protected static HttpTokenList CONNECTION = null; private static String ka = "Keep-Alive"; private static String pc = "Proxy-Connection"; private static String cl = "close"; static { String connection[] = { "Keep-Alive" }; CONNECTION = HttpFactory.makeStringList(connection); DEFAULT_TYPE = HttpFactory.makeMimeType(MimeType.TEXT_HTML); } InputStream is = null; Client client = null; boolean keep = true; Request request = null; private boolean sendBody = true; private boolean dynamic = false; /** * set the reply to be a reply for dynamic content * @param a boolean, true if the reply is generated by a dynamic */ public void setDynamic(boolean dyn) { dynamic = dyn; } /** * is is dynamic or not? */ public boolean isDynamic() { return dynamic; } public void setStatus(Integer status) { setStatus(status.intValue()); } public boolean hasContentLength() { return hasHeader(H_CONTENT_LENGTH); } public boolean hasContentType() { return ( hasHeader(H_CONTENT_TYPE) && ( getHeaderValue(H_CONTENT_TYPE).getValue() != null)); } public void setKeepAlive(String value) { setValue(ka, value); } public void setProxyConnection(String value) { setValue(pc, value); } public boolean keepProxyConnection() { throw new RuntimeException("keepProxyConnection: not implemented!"); } /** * @deprecated */ public FileDescriptor getInputFileDescriptor() { return null; } public void setKeepConnection(boolean onoff) { this.keep = onoff; } public boolean tryKeepConnection() { if ( ! keep ) { addConnection(cl); return false; } else if ( major >= 1 ) { if ( minor >= 1 ) return true; if ( hasContentLength() || (is == null)) { if ( is_proxy ) addProxyConnection(ka); else addConnection(ka); return true; } } return false; } /** * Is this reply a proxy reply. */ protected boolean is_proxy = false; /** * Mark this reply as being a proxy reply. */ public void setProxy (boolean onoff) { is_proxy = onoff; } /** * Sets the reply stream to the given HtmlGenerator stream. * @param g The HtmlGenerator whose output is to be used as the reply body. */ public void setStream (org.w3c.jigsaw.html.HtmlGenerator g) { g.close() ; setContentLength (g.length()) ; setContentType (g.getMimeType()) ; if (sendBody) setStream (g.getInputStream(), true) ; } public boolean hasStream() { return is != null; } /** * Open this reply body stream. * This is used to send the reply body back to the client. * @return An InputStream containing the reply body, which is dumped * back to the client. */ public InputStream openStream () { return is ; } public void setStream(InputStream is) { setStream(is, false); } public synchronized void setStream(InputStream is, boolean closeOld) { if (sendBody) { if (closeOld && (this.is != null)) { try { this.is.close(); } catch (IOException ioex) {}; } this.is = is; } } protected ResourceFilter filters[] = null; protected int infilters = -1; protected void setFilters(ResourceFilter filters[], int infilters) { this.filters = filters; this.infilters = infilters; } protected OutputStream output = null; /** * Get the reply output stream. * @param doEmit Emit that reply before giving out the output stream. * @return An OutputStream instance. * @exception IOException If the output stream could not get opened. */ public synchronized OutputStream getOutputStream(boolean doEmit) throws IOException { if ( output != null ) return output; // Build the output stream: output = client.getOutputStream(); // Call any filters: while ( --infilters >= 0 ) output = filters[infilters].outputFilter(request, this, output); if ( doEmit ) { DataOutputStream dataOutput = new DataOutputStream(output); emit(dataOutput); dataOutput.flush(); setStatus(HTTP.DONE); } // Disable keep-connection: keep = false; return output; } /** * Get that reply output stream. * The reply is first emitted to the stream, and the opened stream * is returned back to the caller. * @return An OutputStream instance. * @exception IOException If the output stream could not get opened. */ public OutputStream getOutputStream() throws IOException { return getOutputStream(true); } /** * Should this reply be chunked ? * @return If so, the reply should prepare itself to send back the * appropriate transfer encoding header, and return * <strong>true</strong>, otherwise it should just return * <strong>false</strong>. */ protected Boolean chunkable = null ; // FIXME should be an HttpTokenList protected static String chunked = "chunked"; public boolean canChunkTransfer() { // Have we already compute this ? if ( chunkable == null ) { // Compute wether we can chunk the reply: if ( hasContentLength() || (is == null)) { chunkable = Boolean.FALSE ; } else if ((major >= 1) && (minor >= 1)) {// String connections[] = getConnection(); chunkable = Boolean.TRUE ;// if (connections != null) {// for (int i = 0; i< connections.length; i++) {// if (connections[i].equalsIgnoreCase("close")) {// chunkable = Boolean.FALSE;// }// }// }// if (chunkable == Boolean.TRUE) addTransferEncoding(chunked); } else { chunkable = Boolean.FALSE ; } } return (chunkable == Boolean.TRUE) ; } /** * Set this reply content. * This method allows to set the reply content to a simple String instance. * @param msg The reply content. * @param encoding, the encoding of the reply */ public void setContent (String msg, String encoding) { if ( ! hasContentType() ) setHeaderValue(H_CONTENT_TYPE, DEFAULT_TYPE) ; byte byteBuffer[]; try { byteBuffer = msg.getBytes(encoding) ; } catch (UnsupportedEncodingException ex) { throw new RuntimeException (this.getClass().getName() + "[setContent] Unable to convert" + "properly char to bytes"); } setContentLength (byteBuffer.length) ; if (sendBody) { ByteArrayInputStream bis = new ByteArrayInputStream (byteBuffer) ; setStream(bis, true); } } // FIXME the bug fix should be in HttpMessage.hasHeader, but it would // be more time consuming, as it would add checks for all headers // and only Content-Type seems to be problematic /** * @param out The output stream to emit the message to. * @param what (fixme doc) * @exception IOException If the message couldn't be emited to the * given stream, due to IO errors. */ public void emit(OutputStream out, int what) throws IOException { int status = getStatus(); if (!hasContentType() && ((status != HTTP.CONTINUE) || (status != HTTP.SWITCHING))) { setHeaderValue(H_CONTENT_TYPE, DEFAULT_TYPE) ; } super.emit(out, what); } public void dump(OutputStream out) { if (!hasContentType()) { setHeaderValue(H_CONTENT_TYPE, DEFAULT_TYPE) ; } super.dump(out); } /** * Set this reply content. * This method allows to set the reply content to a simple String instance. * encoding will be by default "ISO8859_1" * @param msg The reply content. */ public void setContent (String msg) { setContent(msg, "ISO-8859-1"); } /** * Get the entity MIME type. * @return An HttpMimeType object describing the entity's type, or * <strong>null</strong> if udefined. */ public MimeType getContentType() { MimeType mt = super.getContentType(); if (mt == null) { return MimeType.APPLICATION_OCTET_STREAM; } else { return mt; } } /** * Create a new Reply instance for the given client. * @param client The client to who this reply is directed. */ public Reply (Client client) { this.client = client ; } /** * Create a new reply for the given client. * @param client The client ot who the reply is directed. * @reply status The reply status code. */ public Reply(Client client, Request request, short major, short minor, int status) { this (client) ; this.request = request; this.major = major; this.minor = minor; this.keep = true; this.setServer((client != null) ? client.getServer().getSoftware() : null); this.setStatus (status); if (request != null) if (request.getMethod().endsWith(HTTP.HEAD)) sendBody = false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -