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