--- /dev/null
+// PushCacheListener.java\r
+// $Id: PushCacheListener.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.lang.reflect.Method;\r
+import java.lang.reflect.InvocationTargetException;\r
+\r
+import java.net.Socket;\r
+import java.net.ServerSocket;\r
+\r
+import java.util.ArrayList;\r
+\r
+/**\r
+ * PushCacheListener\r
+ * Accepts incoming connections on specified port number and creates \r
+ * PushCacheHandler objects to handle dialogue with client.\r
+ *\r
+ * @author Paul Henshaw, The Fantastic Corporation, Paul.Henshaw@fantastic.com\r
+ * @version $Revision: 1.1 $\r
+ * $Id: PushCacheListener.java,v 1.1 2010/06/15 12:25:44 smhuang Exp $\r
+ */\r
+public class PushCacheListener extends Thread {\r
+ private int _port_number;\r
+ private ServerSocket _socket=null;\r
+ private boolean _running=false;\r
+ private ArrayList _list=null;\r
+ private ShutdownHook _hook=null;\r
+ private boolean _cleaning=false;\r
+\r
+ public class ShutdownHook extends Thread {\r
+ public ShutdownHook() {\r
+ // NULL\r
+ }\r
+\r
+ public void run() {\r
+ try {\r
+ stopRunning();\r
+ }\r
+ catch(Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ /** \r
+ * Register a hanlder with the listener.\r
+ * stopRunning will be called on all registered handlers when\r
+ * the listener is stopped.\r
+ */ \r
+ protected void registerHandler(PushCacheHandler handler) {\r
+ _list.add(handler);\r
+ }\r
+\r
+ /**\r
+ * Reregister a handler from the listener\r
+ */\r
+ protected void deregisterHandler(PushCacheHandler handler) {\r
+ if(!_cleaning) {\r
+ _list.remove(handler);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Close sockets, stop handlers. \r
+ */\r
+ protected void cleanup() {\r
+ if(_cleaning) {\r
+ return;\r
+ }\r
+ _cleaning=true;\r
+ try {\r
+ _running=false;\r
+ if(_socket!=null) {\r
+ _socket.close();\r
+ }\r
+ _socket=null;\r
+ }\r
+ catch(java.io.IOException e) {\r
+ // IGNORE\r
+ }\r
+\r
+ for(int i=0; i<_list.size(); i++) {\r
+ PushCacheHandler handler=(PushCacheHandler)_list.get(i);\r
+ handler.stopRunning();\r
+ }\r
+ _list.clear();\r
+ _list=null;\r
+ }\r
+\r
+ /**\r
+ * Request this thread to exit gracefully\r
+ */\r
+ public void stopRunning() {\r
+ cleanup();\r
+ }\r
+\r
+ /**\r
+ * Listen for connections, creating a handler for each new connection\r
+ */\r
+ public void run() {\r
+ _running=true;\r
+ try { \r
+ while(_running) {\r
+ Socket s=_socket.accept();\r
+ PushCacheHandler handler=new PushCacheHandler(this,s);\r
+ handler.start();\r
+ }\r
+ }\r
+ catch(Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ cleanup();\r
+ }\r
+\r
+ /**\r
+ * Construct a PushCacheListener \r
+ * @param port_number port number on which to listen. \r
+ */\r
+ public PushCacheListener(int port_number) throws java.io.IOException {\r
+ super();\r
+ _port_number=port_number;\r
+ _list=new ArrayList();\r
+ _socket=new ServerSocket(_port_number);\r
+ // add the shutdown hook, if we can!\r
+ Class _c = java.lang.Runtime.class;\r
+ Class _cp[] = { java.lang.Thread.class };\r
+ try {\r
+ Method _m = _c.getMethod("addShutdownHook", _cp);\r
+ Runtime _r = Runtime.getRuntime();\r
+ _hook=new ShutdownHook();\r
+ Object[] _param = { _hook };\r
+ _m.invoke(_r, _param);\r
+ } catch (NoSuchMethodException ex) {\r
+ _hook = null;\r
+ // not using a recent jdk...\r
+ } catch (InvocationTargetException ex) {\r
+ // debug traces?\r
+ } catch (IllegalAccessException ex) {\r
+ // debug traces?\r
+ }\r
+ }\r
+}\r