8b48cd2a7682989d0800744ebc03752e3b43720c
[jalview.git] / src / jalview / ext / rbvi / chimera / ChimeraListener.java
1 package jalview.ext.rbvi.chimera;
2
3 import java.net.BindException;
4
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletResponse;
7
8 import jalview.httpserver.AbstractRequestHandler;
9 import jalview.httpserver.HttpServer;
10 import jalview.structure.SelectionSource;
11
12 /**
13  * This is a simple Http handler that can listen for selections in Chimera.
14  * <p/>
15  * Lifecycle:
16  * <ul>
17  * <li>Start the Chimera process</li>
18  * <li>Start the REST service on Chimera, get the port number it is listening on
19  * </li>
20  * <li>Start the ChimeraListener, get the port number it is listening on</li>
21  * <li>Send a 'listen' command to Chimera with the URL of the listener</li>
22  * </ul>
23  * 
24  * @author gmcarstairs
25  *
26  */
27 public class ChimeraListener extends AbstractRequestHandler implements
28         SelectionSource
29 {
30   /*
31    * A static counter so each listener can be associated with a distinct context
32    * root (/chimera0,1,2,3...). This is needed so we can fetch selections from
33    * multiple Chimera instances without confusion.
34    */
35   private static int chimeraId = 0;
36
37   /*
38    * Path below context root that identifies this handler
39    */
40   private static final String LISTENER_PATH = "chimera";
41
42   /*
43    * Value of chimeraId (0, 1, 2...) for this instance
44    */
45   private int myChimeraId = 0;
46
47   /*
48    * A reference to the object by which we can talk to Chimera
49    */
50   private JalviewChimeraBinding chimeraBinding;
51
52   /*
53    * The URI of this listener
54    */
55   private String uri;
56
57   /**
58    * Constructor that also registers this as an Http request handler on path
59    * /chimeraN, where N is incremented for each instance. Call getUri to get the
60    * resulting URI for this handler.
61    * 
62    * @param chimeraBinding
63    * @throws BindException
64    *           if no free port can be assigned
65    */
66   public ChimeraListener(JalviewChimeraBinding binding)
67           throws BindException
68   {
69     myChimeraId = chimeraId++;
70     this.chimeraBinding = binding;
71     final String path = LISTENER_PATH + myChimeraId;
72     this.uri = HttpServer.getInstance().registerHandler(path, this);
73   }
74
75   /**
76    * Returns the URI on which we are listening
77    * 
78    * @return
79    */
80   public String getUri()
81   {
82     return this.uri;
83   }
84
85   /**
86    * Process a message from Chimera
87    */
88   @Override
89   protected void processRequest(HttpServletRequest request,
90           HttpServletResponse response)
91   {
92     // dumpRequest(request);
93     String message = request.getParameter("chimeraNotification");
94     if ("selection changed".equals(message))
95     {
96       this.chimeraBinding.highlightChimeraSelection();
97     }
98     else
99     {
100       System.err.println("Unexpected chimeraNotification: " + message);
101       // do it anyway for now!
102       this.chimeraBinding.highlightChimeraSelection();
103     }
104   }
105
106   /**
107    * Deregister this listener and close it down
108    * 
109    * @throws Exception
110    */
111   public void shutdown()
112   {
113     try
114     {
115       HttpServer.getInstance().removeHandler(this);
116       stop();
117     } catch (Exception e)
118     {
119       System.err.println("Error stopping chimera listener: "
120               + e.getMessage());
121     }
122   }
123 }