import javax.servlet.http.HttpServletResponse;
import jalview.httpserver.AbstractRequestHandler;
-import jalview.httpserver.HttpServer;
import jalview.structure.SelectionSource;
/**
public class ChimeraListener extends AbstractRequestHandler implements
SelectionSource
{
+ /*
+ * Chimera notification parameter name
+ */
private static final String CHIMERA_NOTIFICATION = "chimeraNotification";
+ /*
+ * Chimera model changed notifications start with this
+ */
private static final String MODEL_CHANGED = "ModelChanged: ";
+ /*
+ * Chimera selection changed notification message
+ */
private static final String SELECTION_CHANGED = "SelectionChanged: selection changed\n";
/*
private static int chimeraId = 0;
/*
- * Path below context root that identifies this handler
+ * Prefix for path below context root (myChimeraId is appended)
*/
- private static final String LISTENER_PATH = "chimera";
+ private static final String PATH_PREFIX = "chimera";
/*
* Value of chimeraId (0, 1, 2...) for this instance
*/
private JalviewChimeraBinding chimeraBinding;
- /*
- * The URI of this listener
- */
- private String uri;
-
/**
- * Constructor that also registers this as an Http request handler on path
+ * Constructor that 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.
*
{
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;
+ setPath(PATH_PREFIX + myChimeraId);
+ registerHandler();
}
/**
}
/**
- * Deregister this listener and close it down
- *
- * @throws Exception
+ * Returns a display name for this service
*/
- public void shutdown()
+ @Override
+ public String getName()
{
- try
- {
- HttpServer.getInstance().removeHandler(this);
- stop();
- } catch (Exception e)
- {
- System.err.println("Error stopping chimera listener: "
- + e.getMessage());
- }
+ return "ChimeraListener";
}
}
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
+import jalview.httpserver.AbstractRequestHandler;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ResidueProperties;
import jalview.structure.AtomSpec;
/*
* Object which listens to Chimera notifications
*/
- private ChimeraListener chimeraListener;
+ private AbstractRequestHandler chimeraListener;
/*
* set if chimera state is being restored from some source - instructs binding
package jalview.httpserver;
import java.io.IOException;
+import java.net.BindException;
import java.util.Collections;
import javax.servlet.ServletException;
*/
public abstract class AbstractRequestHandler extends AbstractHandler
{
+
+ /*
+ * The relative path (below context root) of this handler (without /
+ * separators)
+ */
+ private String path;
+
+ /*
+ * The full URI on which this handler listens
+ */
+ private String uri;
+
/**
* Handle an incoming Http request.
*/
}
}
}
+
+ /**
+ * Returns a display name for the handler
+ *
+ * @return
+ */
+ public abstract String getName();
+
+ /**
+ * 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 " + getName() + ": "
+ + e.getMessage());
+ }
+ }
+
+ /**
+ * Returns the URI on which we are listening
+ *
+ * @return
+ */
+ public String getUri()
+ {
+ return this.uri;
+ }
+
+ /**
+ * Set the URI to this handler
+ *
+ * @param u
+ */
+ protected void setUri(String u)
+ {
+ this.uri = u;
+ }
+
+ /**
+ * Sets the relative path to this handler - do this before registering the
+ * handler.
+ *
+ * @param p
+ */
+ protected void setPath(String p)
+ {
+ this.path = p;
+ }
+
+ /**
+ * Returns the relative path to this handler below the context root (without /
+ * separators)
+ *
+ * @return
+ */
+ public String getPath()
+ {
+ return this.path;
+ }
+
+ /**
+ * Registers the handler with the HttpServer and reports its URI on stdout
+ *
+ * @throws BindException
+ * if no port could be allocated
+ * @throws IllegalStateException
+ * if this method is called before {@link #setPath}
+ */
+ protected void registerHandler() throws BindException
+ {
+ HttpServer.getInstance().registerHandler(this);
+ }
}
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import jalview.rest.RestHandler;
+
/**
* An HttpServer built on Jetty. To use it
* <ul>
private HttpServer() throws BindException
{
startServer();
+
+ /*
+ * Provides a REST server by default; add more programmatically as required
+ */
+ registerHandler(RestHandler.getInstance());
}
/**
}
/**
- * Register a handler for the given path and returns its URI
+ * Register a handler for the given path and set its URI
*
- * @param path
- * a path below the context root (without leading or trailing
- * separator)
* @param handler
* @return
+ * @throws IllegalStateException
+ * if handler path has not been set
*/
- public String registerHandler(String path, AbstractRequestHandler handler)
+ public void registerHandler(AbstractRequestHandler handler)
{
+ String path = handler.getPath();
+ if (path == null)
+ {
+ throw new IllegalStateException(
+ "Must set handler path before registering handler");
+ }
+
// http://stackoverflow.com/questions/20043097/jetty-9-embedded-adding-handlers-during-runtime
ContextHandler ch = new ContextHandler();
ch.setAllowNullPathInfo(true);
+ e.getMessage());
}
- return this.contextRoot + ch.getContextPath().substring(1);
+ handler.setUri(this.contextRoot + ch.getContextPath().substring(1));
+ System.out.println("Jalview " + handler.getName()
+ + " handler started on " + handler.getUri());
}
/**
--- /dev/null
+package jalview.rest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.BindException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import jalview.httpserver.AbstractRequestHandler;
+
+/**
+ * A simple handler to process (or delegate) HTTP requests on /jalview/rest
+ */
+public class RestHandler extends AbstractRequestHandler
+{
+ private static final String MY_PATH = "rest";
+
+ private static final String MY_NAME = "Rest";
+
+ /**
+ * Singleton instance of this class
+ */
+ private static RestHandler instance = null;
+
+ /**
+ * Returns the singleton instance of this class
+ *
+ * @return
+ * @throws BindException
+ */
+ public static RestHandler getInstance() throws BindException
+ {
+ synchronized (RestHandler.class)
+ {
+ if (instance == null)
+ {
+ instance = new RestHandler();
+ }
+ }
+ return instance;
+ }
+
+ /**
+ * Private constructor enforces use of singleton
+ *
+ * @throws BindException
+ */
+ private RestHandler() throws BindException
+ {
+ setPath(MY_PATH);
+
+ /*
+ * We don't register the handler here - this is done as a special case in
+ * HttpServer initialisation; to do it here would invite an infinite loop of
+ * RestHandler/HttpServer constructor
+ */
+ }
+
+ /**
+ * Handle a jalview/rest request
+ *
+ * @throws IOException
+ */
+ @Override
+ protected void processRequest(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ /*
+ * Currently just echoes the request; add helper classes as required to
+ * process requests
+ */
+ final String queryString = request.getQueryString();
+ final String reply = "REST not yet implemented; received "
+ + request.getRequestURL()
+ + (queryString == null ? "" : "?" + queryString);
+ System.out.println(reply);
+
+ try
+ {
+ final PrintWriter writer = response.getWriter();
+ writer.write(reply);
+ writer.close();
+ } catch (IOException e)
+ {
+ System.err.println("Error writing REST response: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Returns a display name for this service
+ */
+ @Override
+ public String getName()
+ {
+ return MY_NAME;
+ }
+
+}