Merge branch 'features/JAL-1596ChimeraREST' into develop
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Sun, 28 Dec 2014 10:34:27 +0000 (10:34 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Sun, 28 Dec 2014 10:34:27 +0000 (10:34 +0000)
1  2 
.classpath
src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java

diff --cc .classpath
@@@ -54,7 -55,5 +54,6 @@@
        <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Plugin.jar"/>
 +      <classpathentry kind="lib" path="lib/jfreesvg-2.1.jar"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Java SE 6 [1.6.0_65-b14-462]"/>
        <classpathentry kind="output" path="classes"/>
  </classpath>
@@@ -20,6 -27,15 +27,15 @@@ import ext.edu.ucsf.rbvi.strucviz2.port
   */
  public class ChimeraManager
  {
 -  private static final boolean debug = true;
++  private static final boolean debug = false;
+   /*
+    * true: use REST API (recommended), false: use stdout/stdin (deprecated)
+    */
++  // TODO remove once definitely happy with using REST
+   private static final boolean USE_REST = true;
 -  // Port number for Chimera REST service
 -  private int restPort;
++  private int chimeraRestPort;
  
    private Process chimera;
  
    {
      chimera = null;
      currentModelsMap.clear();
-     chimeraListenerThreads = null;
 -    if (!USE_REST)
++    if (USE_REST)
++    {
++      this.chimeraRestPort = 0;
++    }
++    else
+     {
+       chimeraListenerThread.requestStop();
+       chimeraListenerThread = null;
+     }
      structureManager.clearOnChimeraExit();
    }
  
      // If no error, then Chimera was launched successfully
      if (error.length() == 0)
      {
-       // Initialize the listener threads
-       chimeraListenerThreads = new ListenerThreads(chimera,
-               structureManager);
-       chimeraListenerThreads.start();
+       if (USE_REST)
+       {
 -        this.restPort = getPortNumber();
++        this.chimeraRestPort = getPortNumber();
++        System.out.println("Chimera REST API on port " + chimeraRestPort);
+       }
+       else
+       {
+         // Initialize the listener threads
+         chimeraListenerThread = new ListenerThreads(chimera,
+                 structureManager);
+         chimeraListenerThread.start();
+       }
        // structureManager.initChimTable();
        structureManager.setChimeraPathProperty(workingPath);
        // TODO: [Optional] Check Chimera version and show a warning if below 1.8
    }
  
    /**
+    * Read and return the port number returned in the reply to --start RESTServer
+    */
+   private int getPortNumber()
+   {
+     int port = 0;
+     InputStream readChan = chimera.getInputStream();
+     BufferedReader lineReader = new BufferedReader(new InputStreamReader(
+             readChan));
+     String response = null;
+     try
+     {
+       // expect: REST server on host 127.0.0.1 port port_number
+       response = lineReader.readLine();
+       String [] tokens = response.split(" ");
+       if (tokens.length == 7 && "port".equals(tokens[5])) {
+         port = Integer.parseInt(tokens[6]);
 -        logger.info("Chimera REST service listening on port " + restPort);
++        logger.info("Chimera REST service listening on port "
++                + chimeraRestPort);
+       }
+     } catch (Exception e)
+     {
+       logger.error("Failed to get REST port number from " + response + ": "
+               + e.getMessage());
+     } finally
+     {
+       try
+       {
+         lineReader.close();
+       } catch (IOException e2)
+       {
+       }
+     }
+     return port;
+   }
+   /**
     * Determine the color that Chimera is using for this model.
     * 
     * @param model
      } finally
      {
        busy = false;
+       if (debug)
+       {
+         System.out.println("Chimera command took "
+                 + (System.currentTimeMillis() - startTime) + "ms: "
+                 + command);
+       }
+     }
+   }
+   /**
+    * Sends the command to Chimera's REST API, and returns any response lines.
+    * 
+    * @param command
+    * @return
+    */
+   protected List<String> sendRestCommand(String command)
+   {
+     // TODO start a separate thread to do this so we don't block?
 -    String restUrl = "http://127.0.0.1:" + this.restPort + "/run";
++    String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run";
+     List<NameValuePair> commands = new ArrayList<NameValuePair>(1);
+     commands.add(new BasicNameValuePair("command", command));
+     List<String> reply = new ArrayList<String>();
+     BufferedReader response = null;
+     try {
+       response = HttpClientUtils.doHttpUrlPost(restUrl,
+               commands);
+       String line = "";
+       while ((line = response.readLine()) != null) {
+         reply.add(line);
+       }
+     } catch (Exception e)
+     {
+       logger.error("REST call " + command + " failed: " + e.getMessage());
+     } finally
+     {
+       if (response != null)
+       {
+         try
+         {
+           response.close();
+         } catch (IOException e)
+         {
+         }
+       }
+     }
+     return reply;
+   }
+   /**
+    * Send a command to stdin of Chimera process, and optionally read any
+    * responses.
+    * 
+    * @param command
+    * @param readReply
+    * @return
+    */
+   protected List<String> sendStdinCommand(String command, boolean readReply)
+   {
+     chimeraListenerThread.clearResponse(command);
+     String text = command.concat("\n");
+     try
+     {
+       // send the command
+       chimera.getOutputStream().write(text.getBytes());
+       chimera.getOutputStream().flush();
+     } catch (IOException e)
+     {
+       // logger.info("Unable to execute command: " + text);
+       // logger.info("Exiting...");
+       logger.warn("Unable to execute command: " + text);
+       logger.warn("Exiting...");
+       clearOnChimeraExit();
+       return null;
+     }
+     if (!readReply)
+     {
+       return null;
      }
+     List<String> rsp = chimeraListenerThread.getResponse(command);
+     return rsp;
    }
  
    public StructureManager getStructureManager()
@@@ -58,6 -58,6 +58,9 @@@ public abstract class JalviewChimeraBin
          SequenceStructureBinding, StructureSelectionManagerProvider
  
  {
++
++  private static final boolean debug = false;
++
    private static final String PHOSPHORUS = "P";
  
    private static final String ALPHACARBON = "CA";
        }
        if (selectioncom.length() > 0)
        {
--        // TODO remove debug output
--        System.out.println("Select regions:\n" + selectioncom.toString());
--        System.out
--                .println("Superimpose command(s):\n" + command.toString());
++        if (debug)
++        {
++          System.out.println("Select regions:\n" + selectioncom.toString());
++          System.out.println("Superimpose command(s):\n"
++                  + command.toString());
++        }
          allComs.append("~display all; chain @CA|P; ribbon "
                  + selectioncom.toString() + ";"+command.toString());
          // selcom.append("; ribbons; ");
        {
          selectioncom.setLength(selectioncom.length() - 1);
        }
--      System.out.println("Select regions:\n" + selectioncom.toString());
++      if (debug)
++      {
++        System.out.println("Select regions:\n" + selectioncom.toString());
++      }
        allComs.append("; ~display all; chain @CA|P; ribbon "
                + selectioncom.toString() + "; focus");
        // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
      }
    }
  
--  boolean debug = false;
--
    private void log(String message)
    {
      System.err.println("## Chimera log: " + message);