// This file is part of PleoCommand: // Interactively control Pleo with psychobiological parameters // // Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Boston, USA. package pleocmd.itfc.cli; import java.awt.EventQueue; import java.io.File; import java.lang.reflect.InvocationTargetException; import pleocmd.Log; import pleocmd.Log.Type; import pleocmd.cfg.ConfigValue; import pleocmd.cfg.Configuration; import pleocmd.exc.ConfigurationException; import pleocmd.itfc.gui.MainFrame; import pleocmd.pipe.Pipe; import pleocmd.pipe.PipePart; public final class CommandLine { private static CommandLine commandLine; private boolean needGUI; private Pipe pipe; private CommandLine() { commandLine = this; } public static CommandLine the() { if (commandLine == null) new CommandLine(); return commandLine; } private Pipe getPipe() { if (needGUI) return MainFrame.the().getPipe(); if (pipe == null) pipe = new Pipe(Configuration.getMain()); return pipe; } private void startPipe() { if (needGUI) MainFrame.the().startPipeThread(); else try { getPipe().configure(); getPipe().pipeAllData(); } catch (final Throwable t) { // CS_IGNORE Log.error(t); } } public void parse(final String[] args) { try { Log.setMinLogType(Type.Info); needGUI = false; for (final String arg : args) if (arg.equals("--gui") || arg.equals("-g")) { needGUI = true; break; } if (needGUI) MainFrame.the(); Log.setGUIStatusKnown(); boolean havePCA = false; for (final String arg : args) { final File file = new File(arg); if (file.isFile()) if (file.getName().endsWith(".pca")) { havePCA = true; Configuration.getMain().readFromFile(file); } else throw new RuntimeException(String.format( "Cannot recognize filetype of '%s'", file)); else parseArgument(arg); } if (havePCA) startPipe(); } catch (final Throwable throwable) { // CS_IGNORE // we need to print the Exception additionally to // logging it because logging itself may have caused // the exception or it just is not yet initialized throwable.printStackTrace(); // CS_IGNORE Log.error(throwable, "Failed to parse command line arguments"); } } private void parseArgument(final String arg) { if ("-d".equals(arg) || "--detailed".equals(arg) || "-v".equals(arg)) Log.setMinLogType(Type.Detail); else if ("-h".equals(arg) || "-?".equals(arg) || "--help".equals(arg)) displayHelp(); else if ("-V".equals(arg) || "--version".equals(arg)) printVersion(); else if ("-g".equals(arg) || "--gui".equals(arg)) displayGUI(); else if (arg.startsWith("--configure=")) configure(arg.substring(12)); else if (arg.startsWith("--c=")) configure(arg.substring(4)); else throw new RuntimeException(String.format( "Cannot recognize argument '%s'", arg)); } private void printVersion() { System.err.println(Version.VERSION_STR); System.err.println("Copyright (C) 2010 Oliver Hoffmann " + "- Hoffmann_Oliver@gmx.de"); System.err.println("Licensed under GNU General Public License " + "version 2 or later"); } private void displayHelp() { printVersion(); System.err.println(); System.err .println("-d --detailed\tPrint detailed (debug) information."); System.err.println("-h -? --help\tPrint this help message."); System.err.println("-V --version\tPrint version and copyright."); System.err.println("-g --gui\tDisplay a GUI and print error " + "messages in dialogs."); System.err.println("<pca-file>\tLoad a previously saved " + "Pipe and execute it."); System.err.println("\t\tPipe is executed after all other arguments " + "have been processed, "); System.err.println("\t\tso additional PCA files " + "on the command line replace the previous one "); System.err.println("\t\tand don't start a second Pipe."); System.err.println("-c --configure\tChange configuration of " + "the Pipe."); System.err .println("\t\tMust be specified after the PCA file. Syntax is:"); System.err.println("\t\t<Name of PipePart>:<Label>:<Value> OR"); System.err.println("\t\t<UID of PipePart>:<Label>:<Value> "); System.err.println("\t\tIf the name of the PipePart is unknown or " + "not unique, an error will be thrown."); System.err .println("\t\tIf the UID of the PipePart is invalid or unknown, " + "an error will be thrown."); System.err.println("\t\tIf the label is unknown, " + "an error will be thrown."); System.err.println("\t\tIf the value is invalid, " + "an error will be thrown."); System.err.println(); System.err.println("Examples:"); System.err.println("Execute a Pipe within the GUI:"); System.err.println("\tpleocommand MyPipe.pca --gui"); System.err.println("Execute a Pipe on the console " + "with additional output:"); System.err.println("\tpleocommand MyPipe.pca --detailed"); System.err.println("Execute a Pipe on the console but " + "change configuration first:"); System.err.println("\tpleocommand MyPipe.pca " + "--c=TcpIpInput:Port:1234 " + "--c=TcpIpInput:\"Read-Timeout (sec):60\""); } private void displayGUI() { assert needGUI; try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { MainFrame.the().showModalGUI(); } }); } catch (final InterruptedException e) { Log.error(e, "Cannot start GUI"); } catch (final InvocationTargetException e) { Log.error(e, "Cannot start GUI"); } } private void configure(final String cfg) { final int idx1 = cfg.indexOf(':'); final int idx2 = cfg.indexOf(':', idx1 + 1); if (idx1 == -1 || idx2 == -1) throw new IllegalArgumentException(String.format( "Expected name or <UID>uid : label : value but found '%s'", cfg)); final String part = cfg.substring(0, idx1).trim(); final String label = cfg.substring(idx1 + 1, idx2).trim(); final String value = cfg.substring(idx2 + 1).trim(); long uid; try { uid = Long.parseLong(part); } catch (final NumberFormatException e) { uid = Long.MIN_VALUE; } final PipePart pp; if (uid != Long.MIN_VALUE) { pp = getPipe().findByUID(uid); if (pp == null) throw new IllegalArgumentException(String.format( "Cannot find PipePart with UID %d in '%s'", uid, getPipe())); } else { pp = getPipe().findByClassName(part); if (pp == null) throw new IllegalArgumentException(String.format( "Cannot find PipePart with name '%s' " + "(or there is more than one) in '%s'", part, getPipe())); } final ConfigValue cv = pp.getGroup().get(label); if (cv == null) throw new IllegalArgumentException(String.format( "Cannot find a configuration with label '%s' in '%s'", label, pp)); try { cv.setFromString(value); } catch (final ConfigurationException e) { throw new IllegalArgumentException(String.format( "Cannot set configuration '%s' in '%s' to '%s'", label, pp, value)); } } }