JAL-3660 Fix for specified output format when using command line arg to convert a...
[jalview.git] / src / jalview / bin / Jalview.java
index 7701229..08cbcb2 100755 (executable)
  */
 package jalview.bin;
 
-import jalview.ext.so.SequenceOntology;
-import jalview.gui.AlignFrame;
-import jalview.gui.Desktop;
-import jalview.gui.PromptUserConfig;
-import jalview.io.AppletFormatAdapter;
-import jalview.io.BioJsHTMLOutput;
-import jalview.io.DataSourceType;
-import jalview.io.FileFormat;
-import jalview.io.FileFormatException;
-import jalview.io.FileFormatI;
-import jalview.io.FileLoader;
-import jalview.io.HtmlSvgOutput;
-import jalview.io.IdentifyFile;
-import jalview.io.NewickFile;
-import jalview.io.gff.SequenceOntologyFactory;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ColourSchemeProperty;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.ws.jws2.Jws2Discoverer;
-
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -64,13 +43,34 @@ import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.swing.LookAndFeel;
 import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
 
 import com.threerings.getdown.util.LaunchUtil;
 
 import groovy.lang.Binding;
 import groovy.util.GroovyScriptEngine;
+import jalview.ext.so.SequenceOntology;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.gui.PromptUserConfig;
+import jalview.io.AppletFormatAdapter;
+import jalview.io.BioJsHTMLOutput;
+import jalview.io.DataSourceType;
+import jalview.io.FileFormat;
+import jalview.io.FileFormatException;
+import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
+import jalview.io.FileLoader;
+import jalview.io.HtmlSvgOutput;
+import jalview.io.IdentifyFile;
+import jalview.io.NewickFile;
+import jalview.io.gff.SequenceOntologyFactory;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemeProperty;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.ws.jws2.Jws2Discoverer;
 
 /**
  * Main class for Jalview Application <br>
@@ -112,21 +112,21 @@ public class Jalview
      */
     {
       // grab all the rights we can for the JVM
-           Policy.setPolicy(new Policy()
-           {
-             @Override
-             public PermissionCollection getPermissions(CodeSource codesource)
-             {
-               Permissions perms = new Permissions();
-               perms.add(new AllPermission());
-               return (perms);
-             }
-       
-             @Override
-             public void refresh()
-             {
-             }
-           });
+      Policy.setPolicy(new Policy()
+      {
+        @Override
+        public PermissionCollection getPermissions(CodeSource codesource)
+        {
+          Permissions perms = new Permissions();
+          perms.add(new AllPermission());
+          return (perms);
+        }
+
+        @Override
+        public void refresh()
+        {
+        }
+      });
     }
   }
 
@@ -198,27 +198,27 @@ public class Jalview
    * main class for Jalview application
    * 
    * @param args
-   *               open <em>filename</em>
+   *          open <em>filename</em>
    */
   public static void main(String[] args)
   {
-//     setLogging(); // BH - for event debugging in JavaScript
+    // setLogging(); // BH - for event debugging in JavaScript
     instance = new Jalview();
     instance.doMain(args);
-}
+  }
 
-  private static void logClass(String name) 
-  {    
-         // BH - for event debugging in JavaScript
-      ConsoleHandler consoleHandler = new ConsoleHandler();
-      consoleHandler.setLevel(Level.ALL);
-      Logger logger = Logger.getLogger(name);
-      logger.setLevel(Level.ALL);
-      logger.addHandler(consoleHandler);
+  private static void logClass(String name)
+  {
+    // BH - for event debugging in JavaScript
+    ConsoleHandler consoleHandler = new ConsoleHandler();
+    consoleHandler.setLevel(Level.ALL);
+    Logger logger = Logger.getLogger(name);
+    logger.setLevel(Level.ALL);
+    logger.addHandler(consoleHandler);
   }
 
   @SuppressWarnings("unused")
-  private static void setLogging() 
+  private static void setLogging()
   {
 
     /**
@@ -229,26 +229,23 @@ public class Jalview
       System.out.println("not in js");
     }
 
-         // BH - for event debugging in JavaScript (Java mode only)
+    // BH - for event debugging in JavaScript (Java mode only)
     if (!Platform.isJS())
     /**
      * Java only
      * 
      * @j2sIgnore
      */
-       {
-               Logger.getLogger("").setLevel(Level.ALL);
-        logClass("java.awt.EventDispatchThread");
-        logClass("java.awt.EventQueue");
-        logClass("java.awt.Component");
-        logClass("java.awt.focus.Component");
-        logClass("java.awt.focus.DefaultKeyboardFocusManager"); 
-       }       
+    {
+      Logger.getLogger("").setLevel(Level.ALL);
+      logClass("java.awt.EventDispatchThread");
+      logClass("java.awt.EventQueue");
+      logClass("java.awt.Component");
+      logClass("java.awt.focus.Component");
+      logClass("java.awt.focus.DefaultKeyboardFocusManager");
+    }
 
   }
-  
-
-  
 
   /**
    * @param args
@@ -263,9 +260,26 @@ public class Jalview
 
     System.out
             .println("Java version: " + System.getProperty("java.version"));
+    System.out.println("Java Home: " + System.getProperty("java.home"));
     System.out.println(System.getProperty("os.arch") + " "
             + System.getProperty("os.name") + " "
             + System.getProperty("os.version"));
+    String val = System.getProperty("sys.install4jVersion");
+    if (val != null)
+    {
+      System.out.println("Install4j version: " + val);
+    }
+    val = System.getProperty("installer_template_version");
+    if (val != null)
+    {
+      System.out.println("Install4j template version: " + val);
+    }
+    val = System.getProperty("launcher_version");
+    if (val != null)
+    {
+      System.out.println("Launcher version: " + val);
+    }
+
     // report Jalview version
     Cache.loadBuildProperties(true);
 
@@ -329,7 +343,7 @@ public class Jalview
         System.out.println("Executing setprop argument: " + defs);
         if (Platform.isJS())
         {
-          Cache.setProperty(defs.substring(0,p), defs.substring(p+1));
+          Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
         }
       }
       defs = aparser.getValue("setprop");
@@ -354,49 +368,89 @@ public class Jalview
 
     desktop = null;
 
-    try
+    // property laf = "crossplatform", "system", "gtk", "metal" or "mac"
+    // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac,
+    // try Quaqua/Vaqua.
+    String lafProp = System.getProperty("laf");
+    String lafSetting = Cache.getDefault("PREFERRED_LAF", null);
+    String laf = "none";
+    if (lafProp != null)
     {
-      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-    } catch (Exception ex)
+      laf = lafProp;
+    }
+    else if (lafSetting != null)
     {
-      System.err.println("Unexpected Look and Feel Exception");
-      ex.printStackTrace();
+      laf = lafSetting;
     }
-    if (Platform.isAMacAndNotJS())
+    boolean lafSet = false;
+    switch (laf)
     {
-
-      LookAndFeel lookAndFeel = ch.randelshofer.quaqua.QuaquaManager
-              .getLookAndFeel();
-      System.setProperty("com.apple.mrj.application.apple.menu.about.name",
-              "Jalview");
-      System.setProperty("apple.laf.useScreenMenuBar", "true");
-      if (lookAndFeel != null)
+    case "crossplatform":
+      lafSet = setCrossPlatformLookAndFeel();
+      if (!lafSet)
       {
-        try
-        {
-          UIManager.setLookAndFeel(lookAndFeel);
-        } catch (Throwable e)
-        {
-          System.err.println(
-                  "Failed to set QuaQua look and feel: " + e.toString());
-        }
+        System.err.println("Could not set requested laf=" + laf);
       }
-      if (lookAndFeel == null
-              || !(lookAndFeel.getClass().isAssignableFrom(
-                      UIManager.getLookAndFeel().getClass()))
-              || !UIManager.getLookAndFeel().getClass().toString()
-                      .toLowerCase().contains("quaqua"))
+      break;
+    case "system":
+      lafSet = setSystemLookAndFeel();
+      if (!lafSet)
       {
-        try
-        {
-          System.err.println(
-                  "Quaqua LaF not available on this plaform. Using VAqua(4).\nSee https://issues.jalview.org/browse/JAL-2976");
-          UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel");
-        } catch (Throwable e)
-        {
-          System.err.println(
-                  "Failed to reset look and feel: " + e.toString());
-        }
+        System.err.println("Could not set requested laf=" + laf);
+      }
+      break;
+    case "gtk":
+      lafSet = setGtkLookAndFeel();
+    {
+      System.err.println("Could not set requested laf=" + laf);
+    }
+      break;
+    case "metal":
+      lafSet = setMetalLookAndFeel();
+    {
+      System.err.println("Could not set requested laf=" + laf);
+    }
+      break;
+    case "nimbus":
+      lafSet = setNimbusLookAndFeel();
+    {
+      System.err.println("Could not set requested laf=" + laf);
+    }
+      break;
+    case "quaqua":
+      lafSet = setQuaquaLookAndFeel();
+    {
+      System.err.println("Could not set requested laf=" + laf);
+    }
+      break;
+    case "vaqua":
+      lafSet = setVaquaLookAndFeel();
+    {
+      System.err.println("Could not set requested laf=" + laf);
+    }
+      break;
+    case "mac":
+      lafSet = setMacLookAndFeel();
+      if (!lafSet)
+      {
+        System.err.println("Could not set requested laf=" + laf);
+      }
+      break;
+    case "none":
+      break;
+    default:
+      System.err.println("Requested laf=" + laf + " not implemented");
+    }
+    if (!lafSet)
+    {
+      setSystemLookAndFeel();
+      if (Platform.isLinux() && !Platform.isJS())
+      {
+        setMetalLookAndFeel();
+      }
+      if (Platform.isAMacAndNotJS())
+      {
+        setMacLookAndFeel();
       }
     }
 
@@ -412,20 +466,16 @@ public class Jalview
 
     if (!headless)
     {
+
       desktop = new Desktop();
       desktop.setInBatchMode(true); // indicate we are starting up
 
       try
       {
         JalviewTaskbar.setTaskbar(this);
-      } catch (Exception e)
-      {
-        System.out.println("Cannot set Taskbar");
-        // e.printStackTrace();
       } catch (Throwable t)
       {
-        System.out.println("Cannot set Taskbar");
-        // t.printStackTrace();
+        System.out.println("Error setting Taskbar: " + t.getMessage());
       }
 
       desktop.setVisible(true);
@@ -539,11 +589,11 @@ public class Jalview
       System.out.println("CMD [-open " + file + "] executed successfully!");
 
       if (!Platform.isJS())
-        /**
-         * ignore in JavaScript -- can't just file existence - could load it?
-         * 
-         * @j2sIgnore
-         */
+      /**
+       * ignore in JavaScript -- can't just file existence - could load it?
+       * 
+       * @j2sIgnore
+       */
       {
         if (!file.startsWith("http://") && !file.startsWith("https://"))
         // BH 2019 added https check for Java
@@ -559,7 +609,7 @@ public class Jalview
         }
       }
 
-        protocol = AppletFormatAdapter.checkProtocol(file);
+      protocol = AppletFormatAdapter.checkProtocol(file);
 
       try
       {
@@ -744,17 +794,37 @@ public class Jalview
             af.createEPS(outputFile);
             continue;
           }
-
-          af.saveAlignment(file, format);
-          if (af.isSaveAlignmentSuccessful())
+          FileFormatI outFormat = null;
+          try
+          {
+            outFormat = FileFormats.getInstance().forName(outputFormat);
+          } catch (Exception formatP)
           {
-            System.out.println("Written alignment in " + format
-                    + " format to " + file);
+            System.out.println("Couldn't parse " + outFormat
+                    + " as a valid Jalview format string.");
           }
-          else
+          if (outFormat != null)
           {
-            System.out.println("Error writing file " + file + " in "
-                    + format + " format!!");
+            if (!outFormat.isWritable())
+            {
+              System.out.println(
+                      "This version of Jalview does not support alignment export as "
+                              + outputFormat);
+            }
+            else
+            {
+              af.saveAlignment(file, outFormat);
+              if (af.isSaveAlignmentSuccessful())
+              {
+                System.out.println("Written alignment in "
+                        + outFormat.getName() + " format to " + file);
+              }
+              else
+              {
+                System.out.println("Error writing file " + file + " in "
+                        + outFormat.getName() + " format!!");
+              }
+            }
           }
 
         }
@@ -779,8 +849,7 @@ public class Jalview
      */
     {
       file = Cache.getDefault("STARTUP_FILE",
-              Cache.getDefault("www.jalview.org",
-                      "http://www.jalview.org")
+              Cache.getDefault("www.jalview.org", "http://www.jalview.org")
                       + "/examples/exampleFile_2_7.jar");
       if (file.equals(
               "http://www.jalview.org/examples/exampleFile_2_3.jar"))
@@ -844,6 +913,107 @@ public class Jalview
     }
   }
 
+  private static boolean setCrossPlatformLookAndFeel()
+  {
+    return setGenericLookAndFeel(false);
+  }
+
+  private static boolean setSystemLookAndFeel()
+  {
+    return setGenericLookAndFeel(true);
+  }
+
+  private static boolean setGenericLookAndFeel(boolean system)
+  {
+    boolean set = false;
+    try
+    {
+      UIManager.setLookAndFeel(
+              system ? UIManager.getSystemLookAndFeelClassName()
+                      : UIManager.getCrossPlatformLookAndFeelClassName());
+      set = true;
+    } catch (Exception ex)
+    {
+      System.err.println("Unexpected Look and Feel Exception");
+      ex.printStackTrace();
+    }
+    return set;
+  }
+
+  private static boolean setSpecificLookAndFeel(String name,
+          String className, boolean nameStartsWith)
+  {
+    boolean set = false;
+    try
+    {
+      for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
+      {
+        if (info.getName() != null && nameStartsWith
+                ? info.getName().toLowerCase()
+                        .startsWith(name.toLowerCase())
+                : info.getName().toLowerCase().equals(name.toLowerCase()))
+        {
+          className = info.getClassName();
+          break;
+        }
+      }
+      UIManager.setLookAndFeel(className);
+      set = true;
+    } catch (Exception ex)
+    {
+      System.err.println("Unexpected Look and Feel Exception");
+      ex.printStackTrace();
+    }
+    return set;
+  }
+
+  private static boolean setGtkLookAndFeel()
+  {
+    return setSpecificLookAndFeel("gtk",
+            "com.sun.java.swing.plaf.gtk.GTKLookAndFeel", true);
+  }
+
+  private static boolean setMetalLookAndFeel()
+  {
+    return setSpecificLookAndFeel("metal",
+            "javax.swing.plaf.metal.MetalLookAndFeel", false);
+  }
+
+  private static boolean setNimbusLookAndFeel()
+  {
+    return setSpecificLookAndFeel("nimbus",
+            "javax.swing.plaf.nimbus.NimbusLookAndFeel", false);
+  }
+
+  private static boolean setQuaquaLookAndFeel()
+  {
+    return setSpecificLookAndFeel("quaqua",
+            ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel().getClass()
+                    .getName(),
+            false);
+  }
+
+  private static boolean setVaquaLookAndFeel()
+  {
+    return setSpecificLookAndFeel("vaqua",
+            "org.violetlib.aqua.AquaLookAndFeel", false);
+  }
+
+  private static boolean setMacLookAndFeel()
+  {
+    boolean set = false;
+    System.setProperty("com.apple.mrj.application.apple.menu.about.name",
+            "Jalview");
+    System.setProperty("apple.laf.useScreenMenuBar", "true");
+    set = setQuaquaLookAndFeel();
+    if ((!set) || !UIManager.getLookAndFeel().getClass().toString()
+            .toLowerCase().contains("quaqua"))
+    {
+      set = setVaquaLookAndFeel();
+    }
+    return set;
+  }
+
   private static void showUsage()
   {
     System.out.println(
@@ -882,6 +1052,8 @@ public class Jalview
                     + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
                     + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
                     + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
+                    + "-jvmmempc=PERCENT\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to PERCENT% of total physical memory detected. This defaults to 90 if total physical memory can be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
+                    + "-jvmmemmax=MAXMEMORY\tOnly available with standalone executable jar or jalview.bin.Launcher. Limit maximum heap size (memory) to MAXMEMORY. MAXMEMORY can be specified in bytes, kilobytes(k), megabytes(m), gigabytes(g) or if you're lucky enough, terabytes(t). This defaults to 32g if total physical memory can be detected, or to 8g if total physical memory cannot be detected. See https://www.jalview.org/help/html/memory.html for more details.\n"
                     + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
   }
 
@@ -920,10 +1092,10 @@ public class Jalview
    * Locate the given string as a file and pass it to the groovy interpreter.
    * 
    * @param groovyscript
-   *                         the script to execute
+   *          the script to execute
    * @param jalviewContext
-   *                         the Jalview Desktop object passed in to the groovy
-   *                         binding as the 'Jalview' object.
+   *          the Jalview Desktop object passed in to the groovy binding as the
+   *          'Jalview' object.
    */
   private void executeGroovyScript(String groovyscript, AlignFrame af)
   {
@@ -1052,8 +1224,8 @@ public class Jalview
   }
 
   /**
-   * Quit method delegates to Desktop.quit - unless running in headless mode when
-   * it just ends the JVM
+   * Quit method delegates to Desktop.quit - unless running in headless mode
+   * when it just ends the JVM
    */
   public void quit()
   {