--- /dev/null
+// EchoCommand.java\r
+// $Id: EchoCommand.java,v 1.1 2010/06/15 12:21:52 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.ssi.commands ;\r
+\r
+import java.util.Date;\r
+import java.util.Dictionary;\r
+\r
+import java.net.URL ;\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.HttpMessage;\r
+import org.w3c.www.http.HttpReplyMessage;\r
+import org.w3c.www.http.HttpRequestMessage;\r
+\r
+import org.w3c.util.ArrayDictionary;\r
+import org.w3c.util.TimeFormatter;\r
+\r
+import org.w3c.jigsaw.http.Reply;\r
+import org.w3c.jigsaw.http.Request;\r
+\r
+import org.w3c.jigsaw.ssi.SSIFrame;\r
+\r
+/**\r
+ * Implementation of the <code>echo</code> SSI command.\r
+ * As extensions, it has the parameters "reqstate" (for echoing\r
+ * Jigsaw request states) and "reqheader" (for echoing request\r
+ * header).\r
+ * <p>Also, it can take the flag "here", whose presence means that the\r
+ * variable is to be interpreted at the deepest request level (in the\r
+ * case of chained internal requests), instead of doing so at the top\r
+ * (external request) level. It inserts the value of a variable in\r
+ * the document. \r
+ * @author Antonio Ramirez <anto@mit.edu>\r
+ */\r
+\r
+public class EchoCommand implements Command {\r
+ private final static String NAME = "echo" ;\r
+\r
+ private static Dictionary modFlags = null ;\r
+\r
+ private static final String[] keys =\r
+ {\r
+ "var",\r
+ "reqstate",\r
+ "reqheader",\r
+ "here"\r
+ } ;\r
+\r
+ static {\r
+ String[] names = {\r
+ "DOCUMENT_NAME" ,\r
+ "DOCUMENT_URI" ,\r
+ "QUERY_STRING_UNESCAPED",\r
+ "SERVER_SOFTWARE" ,\r
+ "SERVER_NAME" ,\r
+ "GATEWAY_INTERFACE" ,\r
+ "SERVER_PROTOCOL" ,\r
+ "SERVER_PORT" ,\r
+ "REQUEST_METHOD" ,\r
+ "PATH_INFO" ,\r
+ "PATH_TRANSLATED" ,\r
+ "SCRIPT_NAME" ,\r
+ "QUERY_STRING" ,\r
+ "REMOTE_HOST" ,\r
+ "REMOTE_ADDR" ,\r
+ "REMOTE_USER" ,\r
+ "AUTH_TYPE" ,\r
+ "REMOTE_IDENT" ,\r
+ "CONTENT_TYPE" ,\r
+ "CONTENT_LENGTH" ,\r
+ "HTTP_ACCEPT" ,\r
+ "HTTP_USER_AGENT" ,\r
+ "DATE_LOCAL" ,\r
+ "DATE_GMT" ,\r
+ "LAST_MODIFIED"\r
+ } ;\r
+\r
+ Boolean[] values = {\r
+ Boolean.FALSE, // DOCUMENT_NAME \r
+ Boolean.FALSE, // DOCUMENT_URI \r
+ Boolean.TRUE, // QUERY_STRING_UNESCAPED\r
+ Boolean.FALSE, // SERVER_SOFTWARE \r
+ Boolean.FALSE, // SERVER_NAME \r
+ Boolean.FALSE, // GATEWAY_INTERFACE \r
+ Boolean.FALSE, // SERVER_PROTOCOL \r
+ Boolean.FALSE, // SERVER_PORT \r
+ Boolean.FALSE, // REQUEST_METHOD \r
+ Boolean.FALSE, // PATH_INFO \r
+ Boolean.FALSE, // PATH_TRANSLATED \r
+ Boolean.FALSE, // SCRIPT_NAME" \r
+ Boolean.TRUE, // QUERY_STRING \r
+ Boolean.FALSE, // REMOTE_HOST \r
+ Boolean.FALSE, // REMOTE_ADDR \r
+ Boolean.FALSE, // REMOTE_USER\r
+ Boolean.FALSE, // AUTH_TYPE\r
+ Boolean.FALSE, // REMOTE_IDENT \r
+ Boolean.FALSE, // CONTENT_TYPE \r
+ Boolean.FALSE, // CONTENT_LENGTH \r
+ Boolean.FALSE, // HTTP_ACCEPT \r
+ Boolean.FALSE, // HTTP_USER_AGENT \r
+ Boolean.TRUE, // DATE_LOCAL \r
+ Boolean.TRUE, // DATE_GMT \r
+ Boolean.FALSE // LAST_MODIFIED\r
+ } ;\r
+\r
+ modFlags = new ArrayDictionary(names,values) ;\r
+ }\r
+\r
+ /**\r
+ * return true if reply can be cached.\r
+ * @return a boolean.\r
+ */\r
+ public boolean acceptCaching() {\r
+ return true;\r
+ }\r
+\r
+ public Reply execute(SSIFrame ssiframe,\r
+ Request request,\r
+ ArrayDictionary parameters,\r
+ Dictionary variables)\r
+ {\r
+ // Get the relevant parameters\r
+ Object[] values = parameters.getMany(keys) ;\r
+ String var = (String) values[0] ;\r
+ String reqstate = (String) values[1] ;\r
+ String reqheader = (String) values[2] ;\r
+ boolean here = values[3] != null ;\r
+\r
+ boolean notMod = false ;\r
+\r
+ Reply reply = ssiframe.createCommandReply(request,HTTP.OK) ;\r
+ String content = null ;\r
+ \r
+ if(var != null) {\r
+ if(var.equals("DOCUMENT_URI")) {\r
+ URL theUrl = here\r
+ ? request.getURL()\r
+ : request.getOriginal().getURL() ;\r
+ if(theUrl != null)\r
+ content = theUrl.toString() ;\r
+ } else {\r
+ Dictionary ssiVars = (Dictionary)\r
+ variables.get(here ? "ssiVars" : "topSsiVars") ;\r
+ \r
+ if(ssiVars == null) return null ;\r
+ \r
+ if(var.equals("DATE_LOCAL")) {\r
+ content = \r
+ TimeFormatter\r
+ .format(new Date(),\r
+ (String) variables.get("datefmt")) ;\r
+ } else if(var.equals("DATE_GMT")) {\r
+ \r
+ // FIXME: won't do formatting\r
+ content = new Date().toGMTString() ;\r
+ \r
+ } else if(var.equals("LAST_MODIFIED")) {\r
+ \r
+ content = TimeFormatter\r
+ .format((Date) ssiVars.get("X_LAST_MODIFIED"),\r
+ (String) variables.get("datefmt")) ;\r
+ \r
+ } else {\r
+ \r
+ content = (String) ssiVars.get(var) ;\r
+ if (content == null)\r
+ content = "";\r
+ }\r
+ }\r
+ long ims = request.getIfModifiedSince() ;\r
+ if(ims != -1) {\r
+ if( var == null ) notMod = true ;\r
+ else {\r
+ Boolean result = (Boolean) modFlags.get(var) ;\r
+ notMod = \r
+ (result == null) ? true : ! result.booleanValue() ;\r
+ }\r
+ }\r
+ } else if(reqstate != null) {\r
+ Object state = here\r
+ ? request.getState(reqstate)\r
+ : request.getOriginal().getState(reqstate) ;\r
+ \r
+ if(state != null)\r
+ content = state.toString() ;\r
+ } else if(reqheader != null) {\r
+ reqheader = reqheader.toLowerCase() ;\r
+ HeaderValue hvalue = here\r
+ ? request.getHeaderValue(reqheader)\r
+ : request.getOriginal().getHeaderValue(reqheader) ;\r
+\r
+ if(hvalue != null)\r
+ content = hvalue.toExternalForm() ;\r
+ } else return null ;\r
+ \r
+ if(content != null) {\r
+ reply.setContent(content) ;\r
+ } else return null ;\r
+\r
+ if(notMod) {\r
+ reply.setStatus(HTTP.NOT_MODIFIED) ;\r
+ reply.setLastModified(request.getIfModifiedSince()) ;\r
+ } \r
+\r
+ return reply ;\r
+ }\r
+\r
+ public String getName()\r
+ {\r
+ return NAME;\r
+ }\r
+\r
+ public String getValue(Dictionary variables, String variable, \r
+ Request request) {\r
+ return "null";\r
+ }\r
+\r
+}\r
+\r
+\r