hatch websocket cont.
authorBill Erickson <berick@esilibrary.com>
Tue, 18 Mar 2014 20:26:22 +0000 (16:26 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 18 Mar 2014 20:26:22 +0000 (16:26 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
src/org/evergreen_ils/hatch/HatchSocket.java
src/org/evergreen_ils/hatch/HatchWebSocketServlet.java

index 14316ce..bfcb772 100644 (file)
 package org.evergreen_ils.hatch;
 
-
-import org.eclipse.jetty.util.FutureCallback;
-
 import java.io.IOException;
+import java.io.File;
+import java.io.BufferedReader;
 import org.eclipse.jetty.websocket.api.Session;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
 import org.eclipse.jetty.websocket.api.annotations.WebSocket;
+import javax.servlet.ServletConfig;
+
+import org.eclipse.jetty.util.ajax.JSON;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import java.util.Arrays;
+import java.util.List;
 
 @WebSocket
 public class HatchSocket {
 
     private Session session;
+    static String[] trustedDomains;
+    static String trustedDomainsString;
+    static boolean trustAllDomains = false;
+    static String profileDirectory;
+    private static final Logger logger = Log.getLogger("HatchSocket");
+
+    /**
+     * config is passed in from our WebSocketServlet container, 
+     * hence the public+static.  Possible to access directly?
+     */
+    public static void configure(ServletConfig config) {
+        logger.info("HatchSocket.configure()");
+
+        trustedDomainsString = 
+            config.getServletContext().getInitParameter("trusted-domains");
+
+        profileDirectory = 
+            config.getServletContext().getInitParameter("profile-directory");
+
+        // default to ~/.evergreen
+        if (profileDirectory == null) {
+            String home = System.getProperty("user.home");
+            profileDirectory = new File(home, ".evergreen").getPath();
+            if (profileDirectory == null) {
+                logger.info("Unable to set profile directory");
+            }
+        }   
+
+        if (trustedDomainsString == null) {
+            logger.info("No trusted domains configured");
+
+        } else {
+
+            if (trustedDomainsString.equals("*")) {
+                trustAllDomains = true;
+                logger.info("All domains trusted");
+
+            } else {
+
+                trustedDomains = trustedDomainsString.split(",");
+                for(String domain : trustedDomains) {
+                    logger.info("Trusted domain: " + domain);
+                }
+            }
+        }
+    }  
+
+    protected boolean verifyOriginDomain() {
+        logger.info("received connection from IP " + 
+            session.getRemoteAddress().getAddress());
+
+        String origin = session.getUpgradeRequest().getHeader("Origin");
+
+        if (origin == null) {
+            logger.warn("No Origin header in request; Dropping connection");
+            return false;
+        } 
+
+        logger.info("connection origin is " + origin);
+
+        if (trustAllDomains) return true;
+
+        if (java.util.Arrays.asList(trustedDomains).indexOf(origin) < 0) {
+            logger.warn("Request from un-trusted domain: " + origin);
+            return false;
+        }
+
+        return true;
+    }
+
 
     @OnWebSocketConnect
     public void onConnect(Session session) {
-        System.out.println("Connect: " + session.getRemoteAddress().getAddress());
         this.session = session;
+        if (!verifyOriginDomain()) session.close();
     }
 
     @OnWebSocketClose
     public void onClose(int statusCode, String reason) {
-        System.out.println("Close: statusCode=" + statusCode + ", reason=" + reason);
+        logger.info("onClose() statusCode=" + statusCode + ", reason=" + reason);
         this.session = null;
     }
 
-    @OnWebSocketMessage
-    public void onMessage(String message) {
-        System.out.println("Message: " + message);
+    private void sendJSONMessage(Object json) {
         try {
-            session.getRemote().sendString("hello : " + message);
+            session.getRemote().sendString(JSON.toString(json));
         } catch (IOException e) {
-            e.printStackTrace();
+            logger.warn(e);
+        }
+    }
+
+    @OnWebSocketMessage
+    public void onMessage(String message) {
+        if (session == null || !session.isOpen()) return;
+        logger.info("onMessage() " + message);
+
+        FileIO io;
+        /*
+         * TODO: inbound message should be a JSON blob
+        String action = request.getParameter("action");
+        String key = request.getParameter("key");
+        String value = request.getParameter("value");
+        */
+        String action = "keys";
+        String key = "";
+        String value = "";
+
+        // all requests require an action
+        /*
+        if (action == null || action.equals("")) {
+            String err = JSON.toString("No action specified in request");
+            sendJSONMessage(err);
+            logger.info(err);
+            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+        */
+
+        if (action.equals("keys")) {
+            io = new FileIO(profileDirectory);
+            String[] keys = io.keys(key); // OK for key to be null
+
+            if (keys != null) {
+                sendJSONMessage(keys);
+            } else {
+                /*
+                response.setStatus(
+                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                    */
+            }
+            return;
+        }
+
+        if (action.equals("printers")) {
+            List printers = new PrintDriver().getPrinters();
+            //response.setStatus(HttpServletResponse.SC_OK);
+            sendJSONMessage(printers);
+            return;
+        }
+
+        // all remaining requests require a key
+        if (key == null || key.equals("")) {
+            String err = "No key specified in request";
+            sendJSONMessage(err);
+            logger.info(err);
+            //response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+            return;
         }
+
+        if (action.equals("get")) {
+            io = new FileIO(profileDirectory);
+            BufferedReader reader = io.get(key);
+            if (reader != null) {
+                String line;
+                //response.setStatus(HttpServletResponse.SC_OK);
+                try {
+                    while ( (line = reader.readLine()) != null) {
+                        // relay lines of text to the caller as we read them
+                        // assume the text content is JSON and return it
+                        // un-JSON-ified.
+                        sendJSONMessage(line);
+                    }
+                } catch (IOException e) {
+                    logger.warn(e);
+                }
+            } else {
+                /*
+                response.setStatus(
+                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                */
+            }
+            return;
+        }
+
+        if (action.equals("delete")) {
+            io = new FileIO(profileDirectory);
+            if (io.delete(key)) {
+                //response.setStatus(HttpServletResponse.SC_OK);
+            } else {
+                //response.setStatus(
+                    //HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            }
+            return;
+        }
+
+        // all remaining actions require value
+        if (value == null) {
+            String err = "No value specified in request";
+            sendJSONMessage(err);
+            logger.info(err);
+            //response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+            return;
+        }
+
+        switch(action) {
+
+            case "print" : 
+                boolean ok = new PrintDriver().printWithDialog(key, value);
+                if (ok) {
+                    //response.setStatus(HttpServletResponse.SC_OK);
+                } else {
+                    //response.setStatus(
+                        //HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                }
+                break;
+
+            case "set" :
+                io = new FileIO(profileDirectory);
+                if (io.set(key, value)) {
+                    //response.setStatus(HttpServletResponse.SC_OK);
+                } else {
+                    //response.setStatus(
+                        //HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                }
+                break;
+
+            case "append" :
+                io = new FileIO(profileDirectory);
+                if (io.append(key, value)) {
+                    //response.setStatus(HttpServletResponse.SC_OK);
+                } else {
+                    //response.setStatus(
+                        //HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                }
+                break;
+
+            default:
+                //response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                sendJSONMessage(
+                    "\"No Such Action: " + action + "\"");
+                logger.info("No such action: " + action);
+        }
+
     }
 }
index 2c3612d..464b0b9 100644 (file)
@@ -1,15 +1,27 @@
 package org.evergreen_ils.hatch;
  
 import javax.servlet.annotation.WebServlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
 import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
 import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
-@SuppressWarnings("serial")
-//@WebServlet(name = "Hatch WebSocket Servlet", urlPatterns = { "/ws" })
 
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
 public class HatchWebSocketServlet extends WebSocketServlet {
+
+    private static final Logger logger = 
+        Log.getLogger("HatchWebSocketServlet");
+
     @Override
     public void configure(WebSocketServletFactory factory) {
         factory.register(HatchSocket.class);
     }
+
+    @Override
+    public void init(ServletConfig config) throws ServletException {  
+        super.init(config); // required for WS
+        HatchSocket.configure(config);
+    }  
 }