Java tutorial
/* $RCSfile$ * $Author: hansonr $ * $Date: 2009-06-26 23:35:44 -0500 (Fri, 26 Jun 2009) $ * $Revision: 11131 $ * * Copyright (C) 2000-2005 The Jmol Development Team * * Contact: jmol-developers@lists.sf.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.openscience.jmol.app; import java.awt.Component; import java.awt.Dimension; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.io.File; import java.util.Comparator; import java.util.Hashtable; import java.util.Map; import java.util.Scanner; import javajs.util.PT; import org.jmol.i18n.GT; import org.jmol.util.Logger; import org.jmol.api.JmolAppAPI; import org.jmol.api.JmolViewer; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.PosixParser; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.HelpFormatter; public class JmolApp implements JmolAppAPI { /** * The data model. */ public int port; public int startupWidth, startupHeight; public Point border; public boolean haveBorder; public File userPropsFile; public HistoryFile historyFile; public boolean haveConsole = true; public boolean haveDisplay = true; public boolean splashEnabled = true; public boolean isDataOnly; public boolean isKiosk; public boolean isPrintOnly; public boolean isSilent; public Map<String, Object> info = new Hashtable<String, Object>(); public Point jmolPosition; public float autoAnimationDelay = 0.2f; // sec private String modelFilename; private String scriptFilename; private String script1 = ""; private String script2 = ""; private boolean scanInput; private String menuFile; //private JmolViewer vwr; //private JmolAdapter modelAdapter; public JmolApp() { // defer parsing until we can set a few options ourselves } /** * standard Jmol application entry point * @param args */ public JmolApp(String[] args) { if (System.getProperty("javawebstart.version") != null) { // If the property is found, Jmol is running with Java Web Start. To fix // bug 4621090, the security manager is set to null. System.setSecurityManager(null); } if (System.getProperty("user.home") == null) { System.err.println(GT._("Error starting Jmol: the property 'user.home' is not defined.")); System.exit(1); } File ujmoldir = new File(new File(System.getProperty("user.home")), ".jmol"); ujmoldir.mkdirs(); userPropsFile = new File(ujmoldir, "properties"); historyFile = new HistoryFile(new File(ujmoldir, "history"), "Jmol's persistent values"); parseCommandLine(args); } public void parseCommandLine(String[] args) { Options options = getOptions(); CommandLine line = null; try { CommandLineParser parser = new PosixParser(); line = parser.parse(options, args); } catch (ParseException exception) { System.err.println("Unexpected exception: " + exception.toString()); } args = line.getArgs(); if (args.length > 0) { modelFilename = args[0]; } checkOptions(line, options); } private Options getOptions() { Options options = new Options(); options.addOption("a", "autoanimationdelay", true, GT._( "delay time in seconds for press-and-hold operation of toolbar animation buttons (default 0.2; numbers > 10 assumed to be milliseconds; set to 0 to disable)")); options.addOption("b", "backgroundtransparent", false, GT._("transparent background")); options.addOption("C", "checkload", false, GT._("check script syntax only - with file loading")); options.addOption("c", "check", false, GT._("check script syntax only - no file loading")); OptionBuilder.withValueSeparator(); options.addOption("D", "property=value", true, GT._("supported options are given below")); options.addOption("d", "debug", false, GT._("debug")); options.addOption("g", "geometry", true, GT.o(GT._("window width x height, e.g. {0}"), "-g500x500")); options.addOption("h", "help", false, GT._("give this help page")); options.addOption("I", "input", false, GT._("allow piping of input from System.Input")); options.addOption("i", "silent", false, GT._("silent startup operation")); options.addOption("J", "jmolscript1", true, GT._("Jmol script to execute BEFORE -s option")); options.addOption("j", "jmolscript2", true, GT._("Jmol script to execute AFTER -s option")); options.addOption("k", "kiosk", false, GT._("kiosk mode -- no frame")); options.addOption("L", "nosplash", false, GT._("start with no splash screen")); options.addOption("l", "list", false, GT._("list commands during script execution")); options.addOption("M", "multitouch", true, GT._("use multitouch interface (requires \"sparshui\" parameter")); options.addOption("m", "menu", true, GT._("menu file to use")); options.addOption("n", "nodisplay", false, GT._("no display (and also exit when done)")); options.addOption("o", "noconsole", false, GT._("no console -- all output to sysout")); options.addOption("P", "port", true, GT._("port for JSON/MolecularPlayground-style communication")); options.addOption("p", "printOnly", false, GT._("send only output from print messages to console (implies -i)")); options.addOption("q", "quality", true, GT._( "JPG image quality (1-100; default 75) or PNG image compression (0-9; default 2, maximum compression 9)")); options.addOption("R", "restricted", false, GT._("restrict local file access")); options.addOption("r", "restrictSpt", false, GT._("restrict local file access (allow reading of SPT files)")); options.addOption("s", "script", true, GT._("script file to execute or '-' for System.in")); options.addOption("T", "headlessmaxtime", true, GT._("headless max time (sec)")); options.addOption("t", "threaded", false, GT._("independent command thread")); options.addOption("w", "write", true, GT.o(GT._("{0} or {1}:filename"), new Object[] { "CLIP", "GIF|JPG|JPG64|PNG|PPM" })); options.addOption("x", "exit", false, GT._("exit after script (implicit with -n)")); return options; } class OptSort implements Comparator<Option> { @Override public int compare(Option o1, Option o2) { char c1 = o1.getOpt().charAt(0); char c2 = o2.getOpt().charAt(0); char uc1 = Character.toUpperCase(c1); char uc2 = Character.toUpperCase(c2); return (uc1 == uc2 ? (c1 < c2 ? -1 : 1) : Character.compare(uc1, uc2)); } } private void checkOptions(CommandLine line, Options options) { if (line.hasOption("h")) { HelpFormatter formatter = new HelpFormatter(); formatter.setOptionComparator(new OptSort()); formatter.printHelp("Jmol", options); // now report on the -D options System.out.println(); System.out.println(GT._("For example:")); System.out.println(); System.out.println("Jmol -ions myscript.spt -w JPEG:myfile.jpg > output.txt"); System.out.println(); System.out.println(GT._( "The -D options are as follows (defaults in parenthesis) and must be called preceding '-jar Jmol.jar':")); System.out.println(); System.out.println(" cdk.debugging=[true|false] (false)"); System.out.println(" cdk.debug.stdout=[true|false] (false)"); System.out.println(" display.speed=[fps|ms] (ms)"); //System.out.println(" JmolConsole=[true|false] (true)"); System.out.println(" logger.debug=[true|false] (false)"); System.out.println(" logger.error=[true|false] (true)"); System.out.println(" logger.fatal=[true|false] (true)"); System.out.println(" logger.info=[true|false] (true)"); System.out.println(" logger.logLevel=[true|false] (false)"); System.out.println(" logger.warn=[true|false] (true)"); System.out.println(" plugin.dir (unset)"); System.out.println(" user.language=[ca|cs|de|en_GB|en_US|es|fr|hu|it|ko|nl|pt_BR|tr|zh_TW] (en_US)"); System.exit(0); } if (line.hasOption("a")) { autoAnimationDelay = PT.parseFloat(line.getOptionValue("a")); if (autoAnimationDelay > 10) autoAnimationDelay /= 1000; Logger.info("setting autoAnimationDelay to " + autoAnimationDelay + " seconds"); } // Process more command line arguments // these are also passed to vwr // debug mode if (line.hasOption("d")) { Logger.setLogLevel(Logger.LEVEL_DEBUG); } // note that this is set up so that if JmolApp is // invoked with just new JmolApp(), we can // set options ourselves. info.put(isDataOnly ? "JmolData" : "Jmol", Boolean.TRUE); // kiosk mode -- no frame if (line.hasOption("k")) info.put("isKiosk", Boolean.valueOf(isKiosk = true)); // port for JSON mode communication if (line.hasOption("P")) port = PT.parseInt(line.getOptionValue("P")); if (port > 0) info.put("port", Integer.valueOf(port)); // print command output only (implies silent) if (line.hasOption("p")) isPrintOnly = true; if (isPrintOnly) { info.put("printOnly", Boolean.TRUE); isSilent = true; } // silent startup if (line.hasOption("i")) isSilent = true; if (isSilent) info.put("silent", Boolean.TRUE); // output to sysout if (line.hasOption("o")) haveConsole = false; if (!haveConsole) // might also be set in JmolData info.put("noConsole", Boolean.TRUE); // transparent background if (line.hasOption("b")) info.put("transparentBackground", Boolean.TRUE); // restricted file access if (line.hasOption("R")) info.put("access:NONE", Boolean.TRUE); // restricted file access (allow reading of SPT files) if (line.hasOption("r")) info.put("access:READSPT", Boolean.TRUE); // independent command thread if (line.hasOption("t")) info.put("useCommandThread", Boolean.TRUE); // list commands during script operation if (line.hasOption("l")) info.put("listCommands", Boolean.TRUE); // no splash screen if (line.hasOption("L")) splashEnabled = false; // check script only -- don't open files if (line.hasOption("c")) info.put("check", Boolean.TRUE); if (line.hasOption("C")) info.put("checkLoad", Boolean.TRUE); // menu file if (line.hasOption("m")) menuFile = line.getOptionValue("m"); // run pre Jmol script if (line.hasOption("J")) script1 = line.getOptionValue("J"); // use SparshUI if (line.hasOption("M")) info.put("multitouch", line.getOptionValue("M")); // run script from file if (line.hasOption("s")) { scriptFilename = line.getOptionValue("s"); } // run post Jmol script if (line.hasOption("j")) { script2 = line.getOptionValue("j"); } //Point b = null; if (haveDisplay && historyFile != null) { Dimension size; String vers = System.getProperty("java.version"); if (vers.compareTo("1.1.2") < 0) { System.out.println("!!!WARNING: Swing components require a " + "1.1.2 or higher version VM!!!"); } if (!isKiosk) { size = historyFile.getWindowSize("Jmol"); if (size != null) { startupWidth = size.width; startupHeight = size.height; } historyFile.getWindowBorder("Jmol"); // first one is just approximate, but this is set in doClose() // so it will reset properly -- still, not perfect // since it is always one step behind. //if (b == null || b.x > 50) border = new Point(12, 116); //else //border = new Point(b.x, b.y); // note -- the first time this is run after changes it will not work // because there is a bootstrap problem. } } // INNER frame dimensions int width = (isKiosk ? 0 : 500); int height = 500; if (line.hasOption("g")) { String geometry = line.getOptionValue("g"); int indexX = geometry.indexOf('x'); if (indexX > 0) { width = PT.parseInt(geometry.substring(0, indexX)); height = PT.parseInt(geometry.substring(indexX + 1)); } else { width = height = PT.parseInt(geometry); } startupWidth = -1; } if (startupWidth <= 0 || startupHeight <= 0) { if (haveDisplay && !isKiosk && border != null) { startupWidth = width + border.x; startupHeight = height + border.y; } else { startupWidth = width; startupHeight = height; } } // write image to clipboard or image file if (line.hasOption("w")) { int quality = -1; if (line.hasOption("q")) quality = PT.parseInt(line.getOptionValue("q")); String type_name = line.getOptionValue("w"); if (type_name != null) { if (type_name.length() == 0) type_name = "JPG:jpg"; if (type_name.indexOf(":") < 0) type_name += ":jpg"; int i = type_name.indexOf(":"); String type = type_name.substring(0, i).toUpperCase(); type_name = type_name.substring(i + 1).trim(); if (type.indexOf(" ") >= 0) { quality = PT.parseInt(type.substring(type.indexOf(" ")).trim()); type.substring(0, type.indexOf(" ")); } if (GraphicsEnvironment.isHeadless()) { Map<String, Object> data = new Hashtable<String, Object>(); data.put("fileName", type_name); data.put("type", type); data.put("quality", Integer.valueOf(quality)); data.put("width", Integer.valueOf(width)); data.put("height", Integer.valueOf(height)); info.put("headlessImage", data); } else script2 += ";write image " + (width > 0 && height > 0 ? width + " " + height : "") + " " + type + " " + quality + " " + PT.esc(type_name); } } if (GraphicsEnvironment.isHeadless()) info.put("headlistMaxTimeMs", Integer.valueOf(1000 * (line.hasOption("T") ? PT.parseInt(line.getOptionValue("T")) : 60))); // the next three are coupled -- if the -n command line option is // given, but -I is not, then the -x is added, but not vice-versa. // however, if this is an application-embedded object, then // it is ok to have no display and no exit. // scanner input if (line.hasOption("I")) scanInput = true; boolean exitUponCompletion = false; if (line.hasOption("n")) { // no display (and exit) haveDisplay = false; exitUponCompletion = !scanInput; } if (line.hasOption("x")) // exit when script completes (or file is read) exitUponCompletion = true; if (!haveDisplay) info.put("noDisplay", Boolean.TRUE); if (exitUponCompletion) { info.put("exit", Boolean.TRUE); script2 += ";exitJmol;"; } } public void startViewer(JmolViewer vwr, SplashInterface splash, boolean isJmolData) { try { } catch (Throwable t) { System.out.println("uncaught exception: " + t); t.printStackTrace(); } if (menuFile != null) vwr.setMenu(menuFile, true); // Open a file if one is given as an argument -- note, this CAN be a // script file if (modelFilename != null) { if (script1 == null) script1 = ""; script1 = (modelFilename.endsWith(".spt") ? "script " : "load ") + PT.esc(modelFilename) + ";" + script1; } // OK, by now it is time to execute the script // then command script if (script1 != null && script1.length() > 0) { if (!isSilent) Logger.info("Executing script: " + script1); if (splash != null) splash.showStatus(GT._("Executing script 1...")); runScript(script1, isJmolData, vwr); } // next the file if (scriptFilename != null) { if (!isSilent) Logger.info("Executing script from file: " + scriptFilename); if (splash != null) splash.showStatus(GT._("Executing script file...")); if (scriptFilename.equals("-")) { // -s - option Scanner scan = new Scanner(System.in); String linein = ""; StringBuilder script = new StringBuilder(); while (scan.hasNextLine() && (linein = scan.nextLine()) != null && !linein.equals("!quit")) script.append(linein).append("\n"); scan.close(); runScript(script.toString(), isJmolData, vwr); } else { vwr.evalFile(scriptFilename); } } // then command script if (script2 != null && script2.length() > 0) { if (!isSilent) Logger.info("Executing script: " + script2); if (splash != null) splash.showStatus(GT._("Executing script 2...")); runScript(script2, isJmolData, vwr); } // scanner input if (scanInput) { new InputScannerThread(vwr, isSilent); } } private void runScript(String script, boolean outputResults, JmolViewer vwr) { if (outputResults) System.out.print(vwr.scriptWaitStatus(script, null)); else vwr.script(script); } @Override public void addHistoryWindowInfo(String name, Component window, Point border) { historyFile.addWindowInfo(name, window, border); } @Override public Point getHistoryWindowPosition(String name) { return historyFile.getWindowPosition(name); } @Override public Dimension getHistoryWindowSize(String name) { return historyFile.getWindowSize(name); } }