JAL-3190 rough Proof of Concept of JalviewJS - Chimera
[jalview.git] / src / ext / edu / ucsf / rbvi / strucviz2 / ChimeraManager.java
index a910a5a..d23f41a 100644 (file)
@@ -32,6 +32,7 @@
  */
 package ext.edu.ucsf.rbvi.strucviz2;
 
+import jalview.util.Platform;
 import jalview.ws.HttpClientUtils;
 
 import java.awt.Color;
@@ -40,6 +41,9 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -47,10 +51,12 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.ws.rs.HttpMethod;
+
 import org.apache.http.NameValuePair;
 import org.apache.http.message.BasicNameValuePair;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
 
 import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType;
 import ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads;
@@ -66,6 +72,12 @@ public class ChimeraManager
 
   private static final boolean debug = false;
 
+  /*
+   * this has to be set to the port number of the REST server
+   * currently being run by Chimera
+   */
+  private int jsPortNo = 51940;
+  
   private int chimeraRestPort;
 
   private Process chimera;
@@ -74,8 +86,8 @@ public class ChimeraManager
 
   private Map<Integer, ChimeraModel> currentModelsMap;
 
-  private Logger logger = LoggerFactory
-          .getLogger(ext.edu.ucsf.rbvi.strucviz2.ChimeraManager.class);
+  private Logger logger = new Logger(); 
+                 //LoggerFactory.getLogger(ext.edu.ucsf.rbvi.strucviz2.ChimeraManager.class);
 
   private StructureManager structureManager;
 
@@ -213,26 +225,28 @@ public class ChimeraManager
   public List<ChimeraModel> openModel(String modelPath, String modelName,
           ModelType type)
   {
-    logger.info("chimera open " + modelPath);
+         String toOpen = Platform.isJS() ? "cifID:" + modelName : modelPath;
+         
+    logger.info("chimera open " + toOpen);
     // stopListening();
     List<ChimeraModel> modelList = getModelList();
     List<String> response = null;
     // TODO: [Optional] Handle modbase models
     if (type == ModelType.MODBASE_MODEL)
     {
-      response = sendChimeraCommand("open modbase:" + modelPath, true);
+      response = sendChimeraCommand("open modbase:" + toOpen, true);
       // } else if (type == ModelType.SMILES) {
       // response = sendChimeraCommand("open smiles:" + modelName, true);
       // modelName = "smiles:" + modelName;
     }
     else
     {
-      response = sendChimeraCommand("open " + modelPath, true);
+      response = sendChimeraCommand("open " + toOpen, true);
     }
     if (response == null)
     {
       // something went wrong
-      logger.warn("Could not open " + modelPath);
+      logger.warn("Could not open " + toOpen);
       return null;
     }
 
@@ -475,6 +489,10 @@ public class ChimeraManager
     List<ChimeraModel> modelList = new ArrayList<>();
     List<String> list = sendChimeraCommand("list models type molecule",
             true);
+    if (Platform.isJS()) 
+    {
+       list.add("model id #0 type Molecule name foo");
+    }
     if (list != null)
     {
       for (String modelLine : list)
@@ -513,6 +531,11 @@ public class ChimeraManager
 
   public boolean isChimeraLaunched()
   {
+         if (Platform.isJS())
+         {
+        this.chimeraRestPort = jsPortNo;
+           return true;
+         }
     boolean launched = false;
     if (chimera != null)
     {
@@ -539,12 +562,19 @@ public class ChimeraManager
    */
   public boolean launchChimera(List<String> chimeraPaths)
   {
+           if (Platform.isJS()) 
+           {
+               // Chimera: run Utilities | REST server
+               // and read port number off reply log, set as jsPortNo
+               this.chimeraRestPort = jsPortNo; 
+               return true;
+           }
     // Do nothing if Chimera is already launched
     if (isChimeraLaunched())
     {
       return true;
     }
-
+    
     // Try to launch Chimera (eventually using one of the possible paths)
     String error = "Error message: ";
     String workingPath = "";
@@ -820,6 +850,11 @@ public class ChimeraManager
    */
   protected List<String> sendRestCommand(String command)
   {
+         if (Platform.isJS()) 
+         {
+                 return sendRestCommandForJS(command);
+         }
+         
     String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run";
     List<NameValuePair> commands = new ArrayList<>(1);
     commands.add(new BasicNameValuePair("command", command));
@@ -854,6 +889,51 @@ public class ChimeraManager
   }
 
   /**
+   * Alternative that uses java.net not apache http client
+   * @param command
+   * @return
+   */
+  protected List<String> sendRestCommandForJS(String command) 
+  {
+    List<String> reply = new ArrayList<>();
+    BufferedReader response = null;
+    try
+       {
+       String encoded = URLEncoder.encode(command, "UTF-8");
+               URL url = new URL("http://127.0.0.1:" + this.chimeraRestPort + "/run?command="+encoded);
+               HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+               connection.setRequestMethod(HttpMethod.GET);
+               connection.setDoInput(true);
+               InputStream is = connection.getInputStream();
+               //      JalviewJS can't read response without access-control-allow-origin * header
+               if (!Platform.isJS())
+               {
+                       response = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+                       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.
    *