/* * Copyright (c) 2010, 2011 The University of Manchester, UK. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * * Neither the names of The University of Manchester nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package uk.org.taverna.server.client.cli; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.io.FileUtils; import uk.org.taverna.server.client.Run; import uk.org.taverna.server.client.RunStatus; import uk.org.taverna.server.client.Server; /** * * @author Robert Haines * */ public final class RunWorkflow extends ConsoleApp { private static final String NAME = "RunWorkflow"; public RunWorkflow() { super(NAME); } @Override public void run(CommandLine line) { // load workflow String workflow = getWorkflow(line); // parse inputs Map<String, String> inputs = getInputs(line); Map<String, File> files = getInputFiles(line); boolean outputRefs = false; if (line.hasOption('r')) { outputRefs = true; } boolean deleteRun = false; if (line.hasOption('D')) { deleteRun = true; } File baclavaIn = null; if (line.hasOption('b')) { baclavaIn = new File(line.getOptionValue('b')); } File baclavaOut = null; if (line.hasOption('o')) { baclavaOut = new File(line.getOptionValue('o', "out.xml")); } // get server address from left over arguments Server server = getServer(line.getArgs()); // create run Run run = server.createRun(workflow); System.out.println("Created run with uuid: " + run.getUUID()); System.out.println("Created at " + run.getCreateTime()); // set inputs if (baclavaIn != null) { try { run.uploadBaclavaFile(baclavaIn); } catch (IOException e) { System.out.println(e); } } else { if (inputs != null) { for (String port : inputs.keySet()) { String value = inputs.get(port); run.setInput(port, value); System.out.format("Set input '%s' to %s\n", port, value); } } if (files != null) { for (String port : files.keySet()) { File file = files.get(port); try { run.uploadInputFile(port, file); System.out.format( "Set input '%s' to use file '%s' as input\n", port, file.getName()); } catch (IOException e) { System.err.format("Could not set input '%s': %s\n", port, e.getMessage()); System.exit(1); } } } } // output baclava? if (baclavaOut != null) { run.setBaclavaOutput(baclavaOut.getName()); } // Start run and wait until it is finished run.start(); System.out.println("Started at " + run.getStartTime()); System.out.print("Running"); while (run.getStatus() == RunStatus.RUNNING) { try { Thread.sleep(1000); System.out.print("."); } catch (InterruptedException e) { } } System.out.println("\nFinished at " + run.getFinishTime()); // get outputs String stdout = run.getConsoleOutput(); String stderr = run.getConsoleError(); int exitcode = run.getExitCode(); System.out.println("Exitcode: " + exitcode); if (stdout != "") { System.out.println("Stdout:\n" + stdout); } if (stderr != "") { System.out.println("Stderr:\n" + stderr); } if (exitcode == 0) { if (baclavaOut != null) { try { FileUtils.writeStringToFile(baclavaOut, run.getBaclavaOutput()); System.out.format("Baclava file written to '%s'\n", baclavaOut); } catch (IOException e) { System.out.format("Could not write baclava file '%s'\n", baclavaOut.getAbsoluteFile()); } } else { System.out.println("Outputs:"); for (String port : run.getOutputPorts()) { System.out.format(" %s -> %s\n", port, run.getOutput(port, outputRefs)); } } } // delete run? if (deleteRun) { run.delete(); System.out.println("Run deleted"); } } private String getWorkflow(CommandLine line) { String workflow = null; if (line.hasOption('w')) { String wkfFilename = line.getOptionValue('w'); File wkfFile = new File(wkfFilename); try { workflow = FileUtils.readFileToString(wkfFile); } catch (IOException e) { System.out.format("Cannot read file '%s'. %s", wkfFilename, e.toString()); } } // try to read workflow stdin if (workflow == null) { try { BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); while (in.ready()) { workflow += in.readLine(); } } catch (IOException e) { System.out.println("Cannot read workflow from input stream."); } } // still no workflow? if (workflow == null) { System.out.println("No workflow provided."); showHelpAndExit(1); } return workflow; } private Map<String, String> getInputs(CommandLine line) { HashMap<String, String> inputs = null; if (line.hasOption('i')) { inputs = new HashMap<String, String>(); String[] pairs = line.getOptionValues('i'); for (String s : pairs) { String[] pair = s.trim().split(":", 2); inputs.put(pair[0], pair[1]); } } return inputs; } private Map<String, File> getInputFiles(CommandLine line) { HashMap<String, File> files = null; if (line.hasOption('f')) { files = new HashMap<String, File>(); String[] pairs = line.getOptionValues('f'); for (String s : pairs) { String[] pair = s.trim().split(":", 2); files.put(pair[0], new File(pair[1])); } } return files; } @Override @SuppressWarnings("static-access") public List<Option> registerOptions() { ArrayList<Option> opts = new ArrayList<Option>(); opts.add(OptionBuilder.withLongOpt("baclava-in") .withDescription("Set baclava file for input port values") .hasArg().withArgName("BACLAVA").create('b')); opts.add(OptionBuilder .withLongOpt("baclava-out") .withDescription( "Return outputs in baclava format. A filename may be specified or 'out.xml' is used") .hasOptionalArg().withArgName("BACLAVA").create('o')); opts.add(OptionBuilder .withLongOpt("workflow") .withDescription( "The workflow to run. If this is not specified then the workflow is read from standard input") .hasArg().withArgName("WORKFLOW").create('w')); opts.add(OptionBuilder.withLongOpt("input") .withDescription("Set input port INPUT to VALUE").hasArg() .withArgName("INPUT:VALUE").create('i')); opts.add(OptionBuilder .withLongOpt("input-file") .withDescription( "Set input port INPUT to use FILE for its input") .hasArg().withArgName("INPUT:FILE").create('f')); opts.add(OptionBuilder .withLongOpt("output-refs") .withDescription( "Return URIs that point to the data items of the output rather than the data items themselves.") .create('r')); opts.add(OptionBuilder .withLongOpt("delete") .withDescription( "Delete the run from the server when it is " + "complete. By default the run and its results are preserved. Note that " + "the run will still be deleted when its expiry time is reached") .create('D')); return opts; } }