JAL-1725 first version of Jetty server / chimera selection listener
[jalview.git] / src / jalview / ext / rbvi / chimera / ChimeraListener.java
diff --git a/src/jalview/ext/rbvi/chimera/ChimeraListener.java b/src/jalview/ext/rbvi/chimera/ChimeraListener.java
new file mode 100644 (file)
index 0000000..8b48cd2
--- /dev/null
@@ -0,0 +1,123 @@
+package jalview.ext.rbvi.chimera;
+
+import java.net.BindException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import jalview.httpserver.AbstractRequestHandler;
+import jalview.httpserver.HttpServer;
+import jalview.structure.SelectionSource;
+
+/**
+ * This is a simple Http handler that can listen for selections in Chimera.
+ * <p/>
+ * Lifecycle:
+ * <ul>
+ * <li>Start the Chimera process</li>
+ * <li>Start the REST service on Chimera, get the port number it is listening on
+ * </li>
+ * <li>Start the ChimeraListener, get the port number it is listening on</li>
+ * <li>Send a 'listen' command to Chimera with the URL of the listener</li>
+ * </ul>
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class ChimeraListener extends AbstractRequestHandler implements
+        SelectionSource
+{
+  /*
+   * A static counter so each listener can be associated with a distinct context
+   * root (/chimera0,1,2,3...). This is needed so we can fetch selections from
+   * multiple Chimera instances without confusion.
+   */
+  private static int chimeraId = 0;
+
+  /*
+   * Path below context root that identifies this handler
+   */
+  private static final String LISTENER_PATH = "chimera";
+
+  /*
+   * Value of chimeraId (0, 1, 2...) for this instance
+   */
+  private int myChimeraId = 0;
+
+  /*
+   * A reference to the object by which we can talk to Chimera
+   */
+  private JalviewChimeraBinding chimeraBinding;
+
+  /*
+   * The URI of this listener
+   */
+  private String uri;
+
+  /**
+   * Constructor that also registers this as an Http request handler on path
+   * /chimeraN, where N is incremented for each instance. Call getUri to get the
+   * resulting URI for this handler.
+   * 
+   * @param chimeraBinding
+   * @throws BindException
+   *           if no free port can be assigned
+   */
+  public ChimeraListener(JalviewChimeraBinding binding)
+          throws BindException
+  {
+    myChimeraId = chimeraId++;
+    this.chimeraBinding = binding;
+    final String path = LISTENER_PATH + myChimeraId;
+    this.uri = HttpServer.getInstance().registerHandler(path, this);
+  }
+
+  /**
+   * Returns the URI on which we are listening
+   * 
+   * @return
+   */
+  public String getUri()
+  {
+    return this.uri;
+  }
+
+  /**
+   * Process a message from Chimera
+   */
+  @Override
+  protected void processRequest(HttpServletRequest request,
+          HttpServletResponse response)
+  {
+    // dumpRequest(request);
+    String message = request.getParameter("chimeraNotification");
+    if ("selection changed".equals(message))
+    {
+      this.chimeraBinding.highlightChimeraSelection();
+    }
+    else
+    {
+      System.err.println("Unexpected chimeraNotification: " + message);
+      // do it anyway for now!
+      this.chimeraBinding.highlightChimeraSelection();
+    }
+  }
+
+  /**
+   * Deregister this listener and close it down
+   * 
+   * @throws Exception
+   */
+  public void shutdown()
+  {
+    try
+    {
+      HttpServer.getInstance().removeHandler(this);
+      stop();
+    } catch (Exception e)
+    {
+      System.err.println("Error stopping chimera listener: "
+              + e.getMessage());
+    }
+  }
+}