Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / jigsaw / src / org / w3c / www / protocol / http / cache / push / Client.java
diff --git a/JMCR-Stable/real-world application/jigsaw/src/org/w3c/www/protocol/http/cache/push/Client.java b/JMCR-Stable/real-world application/jigsaw/src/org/w3c/www/protocol/http/cache/push/Client.java
new file mode 100644 (file)
index 0000000..5cf1ed3
--- /dev/null
@@ -0,0 +1,604 @@
+// Client.java\r
+// $Id: Client.java,v 1.1 2010/06/15 12:25:44 smhuang Exp $\r
+// (c) COPYRIGHT MIT, INRIA and Keio, 2001.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+\r
+package org.w3c.www.protocol.http.cache.push;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.io.DataInputStream;\r
+import java.io.DataOutputStream;\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+\r
+import java.net.Socket;\r
+import java.net.InetAddress;\r
+import java.net.ConnectException;\r
+import java.net.UnknownHostException;\r
+\r
+/**\r
+ * PushCache Client - send messages to push cache server \r
+ *\r
+ * @author Paul Henshaw, The Fantastic Corporation, Paul.Henshaw@fantastic.com\r
+ * @version $Revision: 1.1 $\r
+ * $Id: Client.java,v 1.1 2010/06/15 12:25:44 smhuang Exp $\r
+ */\r
+public class Client {\r
+    /** \r
+     * Return/exit values\r
+     */\r
+    public static final int       OK=0, NO=1, FAILED=-1;\r
+\r
+    /**\r
+     * How many times should we try to reconnect?  10\r
+     */\r
+    public static final int       MAX_TRIES=10;\r
+    \r
+    /**\r
+     * Default hostname - localhost \r
+     */\r
+    public static final String    DEFAULT_SERVER="localhost";\r
+\r
+    /**\r
+     * Version Control Revision\r
+     */\r
+    public static final String    VC_REVISION="$Revision: 1.1 $";\r
+\r
+    /**\r
+     * Version Control Id \r
+     */\r
+    public static final String    VC_ID=\r
+       "$Id: Client.java,v 1.1 2010/06/15 12:25:44 smhuang Exp $";\r
+\r
+    private int                   _verbose=0;\r
+    private int                   _port=-1;\r
+    private String                _host_name="";\r
+    private byte[]                _buffer=null;\r
+    private byte[]                _text_buffer=null;\r
+    private Socket                _socket=null;\r
+    private InputStream           _in=null;\r
+    private OutputStream          _out=null;\r
+    private DataInputStream       _data_stream=null;\r
+    private ByteArrayOutputStream _baos=null;\r
+    private DataOutputStream      _dos=null;\r
+    private int                   _reply_com=-1;\r
+    private String                _reply_command;\r
+\r
+    /**\r
+     * Construct a Client for the default hostname and port number \r
+     */\r
+    public Client()  {\r
+       _host_name=DEFAULT_SERVER;\r
+       _port=PushCacheFilter.DEFAULT_PORT_NUM;\r
+    }\r
+\r
+    /**\r
+     * Construct a Client for the specified hostname and port number\r
+     */\r
+    public Client(String hostname, int port) {\r
+       _host_name=hostname;\r
+       _port=port;\r
+    }\r
+\r
+    /**\r
+     * Construct client with command line arguments and execute\r
+     * command.  Called by main, for use as stand alone program - \r
+     * calls System.exit at the end of execution \r
+     */\r
+    public Client(String[] argv) throws IOException {\r
+       handleArgs(argv);\r
+    }\r
+\r
+    /**\r
+     * Display version information\r
+     */\r
+    protected void version() {\r
+       System.err.println("Jigsaw Push Cache Java Client 1.0 "+\r
+                          "by Paul Henshaw, The Fantastic Corporation\n"+\r
+                          VC_REVISION+"\n"+VC_ID+"\n");\r
+    }\r
+\r
+    /**\r
+     * Display usage/help message\r
+     */\r
+    protected void usage() {\r
+       System.err.println("Usage: -c <command> [-u <url>] [ -p <path>] "+\r
+          "[ -s <server>] [ -P <port> ] "+\r
+          "[ -v ] [ -h ] [ -V ]\n"+\r
+          "\t-s\t\t connect to specified server, default is "+\r
+          DEFAULT_SERVER+".\n"+\r
+          "\t-P\t\t connect to specified port, default is "+\r
+          PushCacheFilter.DEFAULT_PORT_NUM+".\n"+\r
+          "\t-v\t\t verbose operation, repeat for more verbosity.\n"+\r
+          "\t-h\t\t show this help message.\n"+\r
+          "\t-V\t\t show version information.\n\n"+\r
+          "Commands recognised:\n"+\r
+          "\tADD\t\t add <path> to cache as if downloaded from <url>.\n"+\r
+          "\tDEL\t\t delete <url> from cache.\n"+\r
+          "\tPRS\t\t check if <url> is present in cache.\n"+\r
+          "\tCLN\t\t clean cache.\n"+\r
+          "\tNOP\t\t do nothing.\n\n"+\r
+          "Notes:\n"+\r
+          "\tURLs should be fully qualified including trailing slashes\n"+\r
+          "\tfor directories, e.g.:\n"+\r
+          "\t\thttp://www.fantastic.com/\n\trather than:"+\r
+          "\n\t\thttp://www.fantastic.com\n\n"+\r
+          "\tBy default the operation of the PRS command is silent, \n"+\r
+          "\tuse the -v flag to display a text message indicating the\n"+\r
+          "\tpresence of a URL in the cache.\n\n"+\r
+          "\tWhen ADDing a file only the <path> is sent to the server\n"+\r
+          "\tNOT the contents of the file, this means that files can\n"+\r
+          "\tbe added to remote caches only if the client and server\n"+\r
+          "\tshare a file system via NFS or similar.\n\n"+\r
+          "Exit Value:\n"+\r
+          "\tThis program exits with one of the following values:\n"+\r
+          "\t0\t OK, command successful (PRS: URL present)\n"+\r
+          "\t1\t (PRS only) command successful, URL not present\n"+\r
+          "\t255\t command unsuccessful\n");\r
+    }\r
+\r
+    /**\r
+     * Interpret command line arguments\r
+     */\r
+    protected void handleArgs(String[] argv) throws IOException {\r
+       String url=null,path=null,com=null;\r
+       char c;\r
+       boolean got_com=false;\r
+       boolean error=false;\r
+\r
+       for(int i=0; i<argv.length; i++) {\r
+           if(argv[i].charAt(0)!='-' || argv[i].length()!=2) {\r
+               error=true;\r
+               break;\r
+           }\r
+           c=argv[i].charAt(1);\r
+           switch(c) {\r
+           case 'c':\r
+               if(i==argv.length-1) {\r
+                   System.err.println("Missing argument for -"+c);\r
+                   error=true;\r
+                   break;\r
+               }\r
+               com=argv[++i].toUpperCase()+"\0";\r
+               got_com=true;\r
+               break;\r
+\r
+           case 'u':\r
+               if(i==argv.length-1) {\r
+                   System.err.println("Missing argument for -"+c);\r
+                   error=true;\r
+                   break;\r
+               }\r
+               url=argv[++i];\r
+               break;\r
+               \r
+           case 'p':\r
+               if(i==argv.length-1) {\r
+                   System.err.println("Missing argument for -"+c);\r
+                   error=true;\r
+                   break;\r
+               }\r
+               path=argv[++i];\r
+               break;\r
+               \r
+           case 's':\r
+               if(i==argv.length-1) {\r
+                   System.err.println("Missing argument for -"+c);\r
+                   error=true;\r
+                   break;\r
+               }\r
+               _host_name=argv[++i];\r
+               break;\r
+               \r
+           case 'P':\r
+               if(i==argv.length-1) {\r
+                   System.err.println("Missing argument for -"+c);\r
+                   error=true;\r
+                   break;\r
+               }\r
+               try {\r
+                   _port=Integer.parseInt(argv[++i]);\r
+               }\r
+               catch(Exception e) {\r
+                   System.err.println("Invalid port number \""+argv[i]+"\"");\r
+                   _port=-1;\r
+                   error=true;\r
+               }\r
+               break;\r
+               \r
+           case 'v':\r
+               ++_verbose;\r
+               break;\r
+               \r
+           case 'h':\r
+               usage();\r
+               System.exit(OK);\r
+               \r
+           case 'V':\r
+               version();\r
+               System.exit(OK);\r
+               \r
+           default:\r
+               error=true;\r
+           }\r
+       }\r
+\r
+       if(!got_com) {\r
+           System.err.println("No command specified");\r
+           error=true;\r
+       }\r
+\r
+       if(error) {\r
+           usage();\r
+           System.exit(FAILED);\r
+       }\r
+\r
+       if(_port==-1) {\r
+           _port=PushCacheFilter.DEFAULT_PORT_NUM;\r
+       }\r
+\r
+       if(_host_name.length()==0) {\r
+           _host_name=DEFAULT_SERVER;\r
+       }\r
+\r
+       int ev=0;\r
+       try {\r
+           switch(PushCacheProtocol.instance().parseCommand(com)) {\r
+           case PushCacheProtocol.ADD:\r
+               add(path,url);\r
+               break;\r
+           case PushCacheProtocol.DEL:\r
+               del(url);\r
+               break;\r
+           case PushCacheProtocol.PRS:\r
+               if(!isPresent(url)) {\r
+                   ev=1;\r
+               }\r
+               break;\r
+           default:\r
+               simpleCommand(com);\r
+           }\r
+       }\r
+       catch(IllegalArgumentException e) {\r
+           System.err.println(e.getMessage());\r
+           usage();\r
+           ev=FAILED;\r
+       }\r
+       sendBye();\r
+       System.exit(ev);\r
+    }\r
+\r
+    /**\r
+     * Connect to server - try up to MAX_TRIES times, then give up\r
+     */\r
+    protected void connect() throws UnknownHostException, IOException {\r
+       int tries=0;\r
+       while(_socket==null) {\r
+           try {\r
+               _socket=new Socket(_host_name,_port);\r
+               _in=_socket.getInputStream();\r
+               _out=_socket.getOutputStream();\r
+           }\r
+           catch(ConnectException e) {\r
+               System.err.println("Failed to connect to "+_host_name+\r
+                                  " on port "+_port+": "+e.getMessage());\r
+               if(++tries>MAX_TRIES) {\r
+                   throw new \r
+                       ConnectException("Failed to connect to "+_host_name+\r
+                                        " on port "+_port+" after "+   \r
+                                        MAX_TRIES+" attempts:\n"+e);\r
+               }\r
+\r
+               System.err.println("Retrying....");\r
+               try {\r
+                   Thread.sleep(2000);\r
+               }\r
+               catch(InterruptedException ex) {\r
+                   // IGNORE\r
+               }\r
+           }\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Write header information into packet buffer\r
+     */\r
+    protected void writeHeader() throws IOException {\r
+       _baos=new ByteArrayOutputStream();\r
+       _dos=new DataOutputStream(_baos);\r
+       _dos.write(PushCacheProtocol.instance().header(),0,\r
+                  PushCacheProtocol.instance().header().length);\r
+    }\r
+\r
+    /**\r
+     * Read remaining payload length bytes into buffer\r
+     */\r
+    protected void readPayload() throws IOException {\r
+       _data_stream.skipBytes(PushCacheProtocol.COMMAND_LEN);\r
+       int rlen=_data_stream.readInt();\r
+       \r
+       if(rlen==0) {\r
+           return;\r
+       }\r
+       _text_buffer=new byte[rlen];\r
+\r
+       int sofar=0;\r
+       int toread=rlen;\r
+\r
+       sofar=0;\r
+       toread=rlen;\r
+       int rv=-1;\r
+       while(toread>0) {\r
+           rv=_in.read(_text_buffer,sofar,toread);\r
+           if(rv<0) {\r
+               throw new IOException("read returned "+rv);\r
+           }\r
+           sofar+=rv;\r
+           toread-=rv;\r
+       }\r
+       _data_stream=new DataInputStream(new \r
+           ByteArrayInputStream(_text_buffer));\r
+    }\r
+\r
+    /**\r
+     * Await reply packet\r
+     */\r
+    protected void readReply() throws IOException {\r
+       // Read packet\r
+       _buffer=new byte[PushCacheProtocol.PACKET_LEN];\r
+       int rv=_in.read(_buffer);\r
+       if(rv<0) {\r
+           throw new IOException("read returned "+rv);\r
+       }\r
+       if(rv<PushCacheProtocol.PACKET_LEN) {\r
+           throw new IOException("read returned less than PACKET_LEN bytes "+\r
+                                 rv);\r
+       }\r
+\r
+       // Check protocol tag\r
+       if(!PushCacheProtocol.instance().isValidProtocolTag(_buffer)) {\r
+           throw new IOException("Bad protocol tag");\r
+       }\r
+\r
+       // Use a DataInputStream to read bytes and shorts\r
+       _data_stream=\r
+           new DataInputStream(new ByteArrayInputStream(_buffer));\r
+       _data_stream.skipBytes(PushCacheProtocol.TAG_LEN);\r
+\r
+       // Check protol version\r
+       short maj=_data_stream.readShort();\r
+       short min=_data_stream.readShort();\r
+       if(maj!=PushCacheProtocol.MAJ_PROTO_VERSION || \r
+          min>PushCacheProtocol.MIN_PROTO_VERSION) {\r
+           throw new IOException("Bad protocol version");\r
+       }\r
+\r
+       //\r
+       // Check command\r
+       // Note that check includes NULL characters they are\r
+       // part of the command.  \r
+       //\r
+       _reply_command=new String(_buffer, PushCacheProtocol.HEADER_LEN, \r
+                                 PushCacheProtocol.COMMAND_LEN);\r
+       _reply_com=PushCacheProtocol.instance().parseCommand(_reply_command);\r
+       readPayload();\r
+    }\r
+\r
+    /**\r
+     * Handle an ERR message from server - cleanup, throw IOException\r
+     */\r
+    protected void serverError() throws IOException {\r
+       cleanup();\r
+       throw new IOException("Recieved error message from server:\n"\r
+                             +new String(_text_buffer));\r
+    }\r
+\r
+    /**\r
+     * Handle an unexpected message from server - send BYE, throw IOException\r
+     */\r
+    protected void unexpectedReply() throws IOException {\r
+       sendBye();\r
+       throw new IOException("Unexpected reply from server "+\r
+                             _reply_command);\r
+    }\r
+\r
+    /**\r
+     * Cleanup, shutdown and close socket and streams\r
+     */\r
+    protected void cleanup() {\r
+       try {\r
+           if(_in!=null) {\r
+               _in.close();\r
+               _in=null;\r
+           }\r
+           if(_out!=null) {\r
+               _out.close();\r
+               _out=null;\r
+           }\r
+           if(_socket!=null) {\r
+//             _socket.shutdownInput();\r
+//             _socket.shutdownOutput();\r
+               _socket.close();\r
+               _socket=null;\r
+           }\r
+       }\r
+       catch(java.io.IOException e) {\r
+           // IGNORE\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Send a BYE packet, and cleanup\r
+     */\r
+    public void sendBye() throws IOException {\r
+       if(_out!=null) {\r
+           writeHeader();\r
+           _dos.writeBytes("BYE\0");\r
+           _dos.writeInt(0);\r
+           _baos.writeTo(_out);\r
+           cleanup();\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Add file into cache as url\r
+     */\r
+    public void add(String path, String url) \r
+       throws IOException, IllegalArgumentException\r
+    {\r
+       if(url==null || url.length()==0 || path==null || path.length()==0) {\r
+           throw new IllegalArgumentException("Zero length path or url");\r
+       }\r
+\r
+       connect();\r
+       writeHeader();\r
+       _dos.writeBytes("ADD\0");       \r
+       // ulen+plen+2*'\0'+ 2*int\r
+       _dos.writeInt(url.length()+path.length()+10); \r
+       _dos.writeInt(path.length()+1);\r
+       _dos.writeInt(url.length()+1);\r
+       _dos.writeBytes(path+"\0");\r
+       _dos.writeBytes(url+"\0");\r
+       _baos.writeTo(_out);\r
+\r
+       readReply();\r
+       switch(_reply_com) {\r
+       case PushCacheProtocol.OK:\r
+           break;\r
+       case PushCacheProtocol.ERR:\r
+           serverError();\r
+           break;\r
+       default:\r
+           unexpectedReply();\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Throws IllegalArgumentException iff com is not a null \r
+     * terminated string of the correct length\r
+     */\r
+    protected void checkCommand(String com) throws IllegalArgumentException {\r
+       if(com.length()!=PushCacheProtocol.COMMAND_LEN) {\r
+           throw new IllegalArgumentException("Command \""+com+\r
+                                              "\" is wrong length");\r
+       }\r
+       if(com.charAt(3)!='\0') {\r
+           throw new IllegalArgumentException("Command \""+com+\r
+                                              "\" is not null terminated");\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Send a packet with specified command and a url\r
+     */\r
+    public void urlCommand(String com, String url) \r
+       throws IOException, IllegalArgumentException \r
+    {\r
+       if(url==null || url.length()==0) {\r
+           throw new IllegalArgumentException("Zero length url");\r
+       }\r
+       checkCommand(com);\r
+       connect();\r
+       writeHeader();\r
+       _dos.writeBytes(com);\r
+       _dos.writeInt(url.length()+1);\r
+       _dos.writeBytes(url+"\0");\r
+       _baos.writeTo(_out);\r
+    }\r
+\r
+    /**\r
+     * Remove url from cache\r
+     */\r
+    public void del(String url) throws IOException {\r
+       urlCommand("DEL\0",url);\r
+       readReply();\r
+       switch(_reply_com) {\r
+       case PushCacheProtocol.OK:\r
+           break;\r
+       case PushCacheProtocol.ERR:\r
+           serverError();\r
+           break;\r
+       default:\r
+           unexpectedReply();\r
+       }\r
+    }\r
+\r
+    /**\r
+     * True iff url is present in cache\r
+     */ \r
+    public boolean isPresent(String url) throws IOException {\r
+       urlCommand("PRS\0", url);\r
+       readReply();\r
+       switch(_reply_com) {\r
+       case PushCacheProtocol.OK:\r
+           if(_verbose>0) {\r
+               System.err.println(url+" is present");\r
+           }\r
+           return(true);\r
+\r
+       case PushCacheProtocol.NO:\r
+           if(_verbose>0) {\r
+               System.err.println(url+" is not present");\r
+           }\r
+           return(false);\r
+\r
+       case PushCacheProtocol.ERR:\r
+           serverError();\r
+           break;\r
+       default:\r
+           unexpectedReply();\r
+       }\r
+       return(false);\r
+    }\r
+\r
+    /**\r
+     * Send a simple packet with specified command\r
+     */\r
+    public void simpleCommand(String com) throws IOException {\r
+       checkCommand(com);\r
+       connect();\r
+       writeHeader();\r
+       _dos.writeBytes(com);\r
+       _dos.writeInt(0);\r
+       _baos.writeTo(_out);\r
+\r
+       readReply();\r
+       switch(_reply_com) {\r
+       case PushCacheProtocol.OK:\r
+           break;\r
+       case PushCacheProtocol.ERR:\r
+           serverError();\r
+           break;\r
+       default:\r
+           unexpectedReply();\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Send a NOP packet\r
+     */\r
+    public void nop() throws IOException {\r
+       simpleCommand("NOP\0");\r
+    }\r
+\r
+    /**\r
+     * Clean cache - remove all entries\r
+     */\r
+    public void clean() throws IOException {\r
+       simpleCommand("CLN\0");\r
+    }\r
+\r
+    /**\r
+     * For use as stand alone program - constructs Client with argv\r
+     */\r
+    public static void main(String[] argv) {\r
+       try {\r
+           Client c=new Client(argv);\r
+       }\r
+       catch(Exception e) {\r
+           e.printStackTrace();\r
+       }\r
+    }\r
+}\r