/* * The University of Wales, Cardiff Triana Project Software License (Based * on the Apache Software License Version 1.1) * * Copyright (c) 2007 University of Wales, Cardiff. All rights reserved. * * Redistribution and use of the software in source and binary forms, with * or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. The end-user documentation included with the redistribution, if any, * must include the following acknowledgment: "This product includes * software developed by the University of Wales, Cardiff for the Triana * Project (http://www.trianacode.org)." Alternately, this * acknowledgment may appear in the software itself, if and wherever * such third-party acknowledgments normally appear. * * 4. The names "Triana" and "University of Wales, Cardiff" must not be * used to endorse or promote products derived from this software * without prior written permission. For written permission, please * contact triana@trianacode.org. * * 5. Products derived from this software may not be called "Triana," nor * may Triana appear in their name, without prior written permission of * the University of Wales, Cardiff. * * 6. This software may not be sold, used or incorporated into any product * for sale to third parties. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 UNIVERSITY OF WALES, CARDIFF OR ITS 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. * * ------------------------------------------------------------------------ * * This software consists of voluntary contributions made by many * individuals on behalf of the Triana Project. For more information on the * Triana Project, please see. http://www.trianacode.org. * * This license is based on the BSD license as adopted by the Apache * Foundation and is governed by the laws of England and Wales. * */ package org.trianacode.enactment; import org.trianacode.TrianaInstance; import org.trianacode.taskgraph.Task; import org.trianacode.taskgraph.TaskGraph; import org.trianacode.taskgraph.TaskGraphException; import org.trianacode.taskgraph.ser.XMLReader; import org.trianacode.taskgraph.service.SchedulerException; import org.trianacode.taskgraph.tool.Tool; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; /** * A standalone class for executing a taskgraph using specified input data. * * @author Ian Wang * @version $Revision: 4048 $ */ public class CommandLineExec extends TrianaExec { public static int MAX_LENGTH = 20; private Hashtable maptable = new Hashtable(); private ArrayList desclist = new ArrayList(); private String appname; private int argnum; /** * Constructs a TrianaExec to execute a clone of the specified taskgraph. Uses a default tool table */ public CommandLineExec(String appname, TaskGraph taskgraph) throws TaskGraphException { super(taskgraph); this.appname = appname; } /** * Constructs a TrianaExec to execute a clone of the specified tool. Uses a default tool table. */ public CommandLineExec(String appname, Tool tool) throws TaskGraphException { super(tool); this.appname = appname; } /** * Sets the number of required arguments */ public void setNumberOfRequiredArguments(int argnum) { this.argnum = argnum; } /** * @return the number of required arguments */ public int getNumberOfRequiredArguments() { return argnum; } /** * Sets the specified parameter, where paramname is a mapped paramname or of the form groupname.taskname.paramname */ public void setParameter(String paramname, Object value) { String[] paramnames; Task subtask; if (isMapped(paramname)) { paramnames = getMappedParameters(paramname); } else { paramnames = new String[]{paramname}; } for (int count = 0; count < paramnames.length; count++) { subtask = getTask(paramnames[count]); if (subtask != null) { subtask.setParameter(getParameterName(paramnames[count]), value); } } } /** * @return the specified parameter value, where paramname is a mapped paramname or of the form * groupname.taskname.paramname (returns null if parameter not set). Note that if the paramname is mapped to * multiple parameters then the value of one is returned (but it is not defined which one!). */ public Object getParameter(String paramname) { Task subtask; if (isMapped(paramname)) { paramname = getMappedParameters(paramname)[0]; } subtask = getTask(paramname); if (subtask != null) { return subtask.getParameter(getParameterName(paramname)); } else { return null; } } /** * Maps a parameter of the form groupname.taskname.paramname to a simple string (e.g. file). At the commandline the * application user can write java TrianaExec -file afile.dat taskgraph.xml, as opposed to the full parameter name. * Note that a string can be mapped to multiple parameter names. Also note that the preceeding - should not be * included in the map string. */ public void mapParameter(String map, String paramname) { mapParameter(map, paramname, null); } /** * Maps a parameter of the form groupname.taskname.paramname to a simple string (e.g. verbose), along with the value * that the parameter is set to (e.g. new Boolean(true)). At the commandline the application user can write java * TrianaExec -verbose taskgraph.xml. Note that a string can be mapped to multiple parameter names+values. */ public void mapParameter(String map, String paramname, Object value) { if (map.startsWith("-")) { map = map.substring(1); } if (!maptable.containsKey(map)) { maptable.put(map, new ArrayList()); } ArrayList maplist = (ArrayList) maptable.get(map); if (!maplist.contains(paramname)) { maplist.add(new Mapping(paramname, value)); } } /** * Unmaps all the mappings from a string. */ public void unmap(String map) { maptable.remove(map); } /** * @return true if the specified string is a map */ public boolean isMapped(String map) { return maptable.containsKey(map); } /** * @return the parameter names mapped to the specified map */ public String[] getMappedParameters(String map) { if (!maptable.containsKey(map)) { return new String[0]; } ArrayList mappings = (ArrayList) maptable.get(map); String[] paramnames = new String[mappings.size()]; for (int count = 0; count < paramnames.length; count++) { paramnames[count] = ((Mapping) mappings.get(count)).getParameterName(); } return paramnames; } /** * @return the value mapped to the specified map/paramname pair (or null if not specified) */ public boolean isMappedValue(String map, String paramname) { if (!maptable.containsKey(map)) { return false; } ArrayList mappings = (ArrayList) maptable.get(map); Mapping mapping; for (int count = 0; count < mappings.size(); count++) { mapping = (Mapping) mappings.get(count); if (mapping.getParameterName().equals(paramname)) { return mapping.getValue() != null; } } return false; } /** * @return the value mapped to the specified map/paramname pair (or null if not specified) */ public Object getMappedValue(String map, String paramname) { if (!maptable.containsKey(map)) { return null; } ArrayList mappings = (ArrayList) maptable.get(map); Mapping mapping; for (int count = 0; count < mappings.size(); count++) { mapping = (Mapping) mappings.get(count); if (mapping.getParameterName().equals(paramname)) { return mapping.getValue(); } } return null; } /** * Sets a description for the specified map string. This description can take the form "<item tag> main description" * if required. */ public void setDescription(String map, String description) { removeDescription(map); desclist.add(new Description(map, description)); } /** * Removes the description for the specified map */ public void removeDescription(String map) { Description desc = getDescriptionItem(map); if (desc != null) { desclist.remove(desc); } } /** * @return the full description string for the specified map */ public String getFullDescription(String map) { Description desc = getDescriptionItem(map); if (desc != null) { return desc.getDescription(); } else { return null; } } /** * @return the description string for the specified map. If the description string was specified as "<item tag> main * description" then only the main description is returned. */ public String getDescription(String map) { Description desc = getDescriptionItem(map); if (desc != null) { String dstr = desc.getDescription(); if (dstr.startsWith("<") && (dstr.indexOf('>') > -1)) { return dstr.substring(dstr.indexOf('>') + 1).trim(); } else { return desc.getDescription().trim(); } } else { return null; } } /** * @return the item tag for the specified map if the description was specified as "<item tag> main description". * Otherwise null is returned. */ public String getItemTag(String map) { Description desc = getDescriptionItem(map); if (desc != null) { String dstr = desc.getDescription(); if (dstr.startsWith("<") && (dstr.indexOf('>') > -1)) { return dstr.substring(1, dstr.indexOf('>')); } } return null; } /** * @return the description instance for the specified map */ private Description getDescriptionItem(String map) { Iterator desciter = desclist.iterator(); Description desc; while (desciter.hasNext()) { desc = (Description) desciter.next(); if (desc.getMap().equals(map)) { return desc; } } return null; } /** * @return the paramname for the specified groupname.taskname.paramname */ private String getParameterName(String paramname) { if (paramname.indexOf('.') == -1) { return paramname; } else { return paramname.substring(paramname.indexOf('.') + 1); } } /** * @return the task for the specified groupname.taskname.paramname string */ private Task getTask(String paramname) { if (paramname.indexOf('.') == -1) { return getTask(); } else { String[] tasknames = paramname.split("\\."); Task subtask = getTask(); for (int count = 0; count < tasknames.length - 1; count++) { if ((subtask == null) || (!(subtask instanceof TaskGraph))) { return null; } subtask = ((TaskGraph) subtask).getTask(tasknames[count]); } return subtask; } } /** * Initialises the parameters for the specified command line arguments. * * @return either a help message or error message, or null if no message is needed. */ public String initParameters(String[] args) { String maparg; String val; boolean map; boolean valused; int hashptr = 1; int ptr = 0; while (ptr < args.length) { maparg = args[ptr].substring(1); map = args[ptr].charAt(0) == '-'; valused = false; if (ptr + 1 < args.length) { val = args[ptr + 1]; } else { val = null; } if (map && maparg.equals("?")) { return getHelpMessage(); } else if (map && isMapped(maparg)) { String[] params = getMappedParameters(maparg); for (int count = 0; count < params.length; count++) { if (isMappedValue(maparg, params[count])) { setParameter(params[count], getMappedValue(maparg, params[count])); } else { setParameter(params[count], val); valused = true; } } } else if (map && (getTask(maparg) != null)) { setParameter(maparg, val); valused = true; } else if (isMapped("#" + hashptr)) { setParameter("#" + hashptr, args[ptr]); hashptr++; } else { return "Error: Unknown argument/option " + args[ptr] + "\n\n" + getHelpMessage(); } if (valused) { ptr++; } ptr++; } if (hashptr <= getNumberOfRequiredArguments()) { return "Error: Incomplete arguments\n\n" + getHelpMessage(); } return null; } public String getHelpMessage() { Iterator iter = desclist.iterator(); String mess = ""; String tmp; Description desc; int optionlen = getOptionLength(); mess += "Usage: java " + appname + " [options]"; for (int count = 1; count <= getNumberOfRequiredArguments(); count++) { if (getItemTag("#" + count) != null) { mess += " <" + getItemTag("#" + count) + ">"; } else { mess += " <#" + count + ">"; } } mess += "\n"; for (int count = 1; count <= getNumberOfRequiredArguments(); count++) { if ((getDescription("#" + count) != null) && (!getDescription("#" + count).equals(""))) { if (getItemTag("#" + count) != null) { tmp = " <" + getItemTag("#" + count) + ">"; } else { tmp = " <#" + count + ">"; } while (tmp.length() < optionlen) { tmp += " "; } mess += tmp + getDescription("#" + count) + "\n"; } } mess += "\n"; if (desclist.size() > 0) { mess += "Where options include:\n"; } while (iter.hasNext()) { desc = (Description) iter.next(); if (!desc.getMap().startsWith("#")) { tmp = " -" + desc.map + " "; if (getItemTag(desc.getMap()) != null) { tmp += "<" + getItemTag(desc.getMap()) + "> "; } else { tmp += " "; } while (tmp.length() < optionlen) { tmp += " "; } mess += tmp + getDescription(desc.getMap()) + "\n"; } } return mess; } private int getOptionLength() { Iterator iter = desclist.iterator(); int maxlength = 0; int length; Description desc; while (iter.hasNext()) { desc = (Description) iter.next(); length = 5 + desc.getMap().length() + 2; if (getItemTag(desc.getMap()) != null) { length += 3 + getItemTag(desc.getMap()).length(); } maxlength = Math.max(maxlength, length); } return Math.min(maxlength, MAX_LENGTH); } public static void main(String[] args) { System.out.println("CommandLineExec.main CALLED"); if (args.length == 0) { System.out.println("Error: Taskgraph xml file not specified"); System.out.println("Usage: java CommandLineExec <xmlfile>"); return; } File file = new File(args[0]); if (!file.exists()) { System.out.println("File not found: " + file.getAbsolutePath()); return; } try { TrianaInstance engine = null; try { engine = new TrianaInstance(args); engine.init(); } catch (Exception e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. System.exit(1); } XMLReader reader = new XMLReader(new FileReader(file)); CommandLineExec exec = new CommandLineExec("CommandLineExec <xmlfile> ", reader.readComponent(engine.getProperties())); String[] argsub = new String[args.length - 1]; System.arraycopy(args, 1, argsub, 0, argsub.length); exec.initParameters(argsub); exec.run(new Object[0]); while (!exec.isFinished()) { System.out.println("CommandLineExec.main WAITING FOR TASKGRAPH TO FINISH"); try { Thread.sleep(100); } catch (InterruptedException e) { } } exec.dispose(); } catch (FileNotFoundException except) { System.out.println("File not found: " + file.getAbsolutePath()); } catch (TaskGraphException except) { System.out.println("Invalid taskgraph file: " + file.getAbsolutePath()); } catch (SchedulerException except) { System.out.println("Error running taskgraph: " + except.getMessage()); } catch (IOException except) { except.printStackTrace(); } System.exit(0); } private class Mapping { private String paramname; private Object value; public Mapping(String paramname) { this.paramname = paramname; } public Mapping(String paramname, Object value) { this.paramname = paramname; this.value = value; } public String getParameterName() { return paramname; } public Object getValue() { return value; } } private class Description { private String map; private String desc; public Description(String map, String desc) { this.map = map; this.desc = desc; } public String getMap() { return map; } public String getDescription() { return desc; } } }