package org.trianacode.shiwaall.iwir.execute; import org.apache.commons.io.FileUtils; import org.shiwa.fgi.iwir.AbstractPort; import org.trianacode.enactment.StreamToOutput; import org.trianacode.taskgraph.Node; import org.trianacode.taskgraph.Task; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; // TODO: Auto-generated Javadoc /** * Created by IntelliJ IDEA. * User: Ian Harvey * Date: 24/06/2011 * Time: 14:56 * To change this template use File | Settings | File Templates. */ public class Executable implements ExecutableInterface, Serializable { /** The task type. */ private String taskType; /** The Constant TASKTYPE. */ public static final String TASKTYPE = "taskType"; /** The Constant EXECUTABLE. */ public static final String EXECUTABLE = "executable"; /** The args. */ private String[] args = new String[0]; /** The working dir. */ private File workingDir = null; /** The primary exec. */ private String primaryExec = ""; /** The node name to port name. */ // private transient HashMap<String, String> nodeNameToPortName; /** The task name. */ private String taskName = ""; /** The input port to file map. */ // private transient HashMap<InputPort, File> inputPortToFileMap; /** The output port to file map. */ // private transient HashMap<OutputPort, File> outputPortToFileMap; private String JSDLstring = ""; // private Tool tool = null; //transient, as Executable node can't be serialised private transient ArrayList<ExecutableNode> executableNodes; // Used only when saving and loading these tasks, don't use them otherwise private HashMap<Integer, String> inputNodeNumberToFilename = new HashMap<Integer, String>(); private HashMap<Integer, String> outputNodeNumberToFilename = new HashMap<Integer, String>(); /** * Instantiates a new executable. * * @param taskType the task type */ public Executable(String taskType) { this.taskType = taskType; // nodeNameToPortName = new HashMap<String, String>(); // inputPortToFileMap = new HashMap<InputPort, File>(); // outputPortToFileMap = new HashMap<OutputPort, File>(); executableNodes = new ArrayList<ExecutableNode>(); } /** * Run process. */ private void runProcess() { try{ ProcessBuilder pb = new ProcessBuilder(args); if(workingDir != null){ pb.directory(workingDir); } Process process = pb.start(); System.out.println("Running " + process.toString()); new StreamToOutput(process.getErrorStream(), "err").start(); new StreamToOutput(process.getInputStream(), "std.out").start(); int returnCode = process.waitFor(); System.out.println("Runtime process finished with code " + returnCode); } catch (Exception e){ e.printStackTrace(); } } /* (non-Javadoc) * @see org.trianacode.shiwaall.iwir.execute.ExecutableInterface#run() */ public void run() { System.out.println("TaskType : " + taskType); System.out.println("Running with no inputs or outputs"); runProcess(); } /** * Serialize. * * @param object the object * @param file the file */ private void serialize(Object object, File file) { byte[] data = object.toString().getBytes(); try { ObjectOutputStream outstream = new ObjectOutputStream(new FileOutputStream(file)); for (int count = 0; count < data.length; count++) { outstream.writeObject(data[count]); } outstream.close(); } catch (Exception except) { } } /* (non-Javadoc) * @see org.trianacode.shiwaall.iwir.execute.ExecutableInterface#run(java.util.HashMap, java.lang.Object[]) */ public void run(HashMap<Node, Object> inputs, Object[] outputs) { System.out.println("TaskType : " + taskType); System.out.println("Running with inputs, producing outputs"); // System.out.println(nodeNameToPortName.toString()); // System.out.println(inputPortToFileMap.toString()); for(Node node : inputs.keySet()){ File executableInputFile = getInputFileForNode(node); Object input = inputs.get(node); if(input instanceof String){ try { File file = new File((String) input); if(file.exists()){ System.out.println("Executable input : " + executableInputFile); System.out.println("Input " + file.getAbsolutePath() + " exists " + file.exists()); FileUtils.copyFile(file, executableInputFile); } } catch (IOException e) { e.printStackTrace(); } } else if(input instanceof File){ if(((File) input).exists()){ try { FileUtils.copyFile((File) input, executableInputFile); } catch (IOException e) { e.printStackTrace(); } } } else { serialize(input, executableInputFile); } } // for (int i = 0; i < outputs.length; i++) { // String output = ""; // // for (int j = 0; j < inputs.length; j++) { // Object input = inputs[j]; // System.out.println(input); // output += input.toString(); // } // // outputs[i] = output; // } System.out.println("TaskType : " + taskType); System.out.println("Running with inputs"); runProcess(); } /** * Gets the task type. * * @return the task type */ public String getTaskType() { return taskType; } /** * Sets the working dir. * * @param workingDir the new working dir */ public void setWorkingDir(File workingDir) { this.workingDir = workingDir; } /** * Sets the args. * * @param args the new args */ public void setArgs(String[] args) { this.args = args; } /** * Gets the working dir. * * @return the working dir */ public File getWorkingDir() { return workingDir; } /** * Gets the args. * * @return the args */ public String[] getArgs() { return args; } /** * Sets the primary exec. * * @param primaryExec the new primary exec */ public void setPrimaryExec(String primaryExec) { this.primaryExec = primaryExec; } /** * Gets the primary exec. * * @return the primary exec */ public String getPrimaryExec() { return primaryExec; } /** * Gets the ports. * * @return the ports */ // public HashMap<String, String> getPorts() { // return nodeNameToPortName; // } /** * Adds the port. * * @param nodeName the node name * @param portName the port name */ // public void addPort(String nodeName, String portName) { // System.out.println(nodeName + " maps to " + portName); // nodeNameToPortName.put(nodeName, portName); // } /** * Sets the task name. * * @param taskName the new task name */ public void setTaskName(String taskName) { this.taskName = taskName; } /** * Gets the task name. * * @return the task name */ public String getTaskName() { return taskName; } /** * Adds the input file. * * @param inputPort the input port * @param inputFile the input file */ // public void addInputFile(InputPort inputPort, File inputFile) { // inputPortToFileMap.put(inputPort, inputFile); // } /** * Gets the input file for node. * * @param node the node * @return the input file for node */ private File getInputFileForNode(Node node){ // System.out.println("Looking for a file for " + node.getBottomLevelNode().getName()); // String portName = nodeNameToPortName.get(node.getBottomLevelNode().getName()); // if(portName != null){ // System.out.println("IWIR port " + portName); // for(InputPort inputPort : inputPortToFileMap.keySet()){ // if(inputPort.getName().equals(portName)){ // File file = inputPortToFileMap.get(inputPort); // System.out.println("Input node to file : " + file.getAbsolutePath()); // return file; // } // } // } // ArrayList<ExecutableNode> execNodes = getExecutableNodes(true); for(ExecutableNode executableNode : executableNodes) { if(executableNode.getNode() != null) { // System.out.println(node + " " + executableNode.getNode()); //TODO ouch if(executableNode.getNode().getName().equals(node.getName())){ String filename = executableNode.getFilename(); if(filename != null && !filename.equals("")) { return new File(workingDir, filename); } } } } return null; } /** * Gets the output file for node. * * @param node the node * @return the output file for node */ public File getOutputFileForNode(Node node) { // String portName = nodeNameToPortName.get(node.getBottomLevelNode().getName()); // if(portName != null) { // System.out.println("IWIR output port " + portName); // for(OutputPort outputPort : outputPortToFileMap.keySet()){ // if(outputPort.getName().equals(portName)){ // File file = outputPortToFileMap.get(outputPort); // System.out.println("Output node to file : " + file.getAbsolutePath()); // return file; // } // } // } // ArrayList<ExecutableNode> execNodes = getExecutableNodes(false); for(ExecutableNode executableNode : executableNodes) { if(executableNode.getNode() != null) { if(executableNode.getNode().getName().equals(node.getName())){ String filename = executableNode.getFilename(); if(filename != null && !filename.equals("")) { return new File(workingDir, filename); } } } } return null; //To change body of created methods use File | Settings | File Templates. } /** * Adds the output file. * // * @param outputPort the output port // * @param outputFile the output file */ // public void addOutputFile(OutputPort outputPort, File outputFile) { // outputPortToFileMap.put(outputPort, outputFile); // } @Override public String toString(){ return primaryExec; } public void setJSDLstring(String JSDLstring) { this.JSDLstring = JSDLstring; } public String getJSDLstring() { return JSDLstring; } // public void setTool(Tool tool) { // this.tool = tool; // } // public Tool getTool() { // return tool; // } private void updatedExeceutableNode() { System.out.println("Updated Executable node" + Arrays.toString(executableNodes.toArray())); Task task = null; //get a the task without having to remember a reference to it //keeps things tidy and serializable for(ExecutableNode executableNode : executableNodes){ if(executableNode.getNode() != null){ task = executableNode.getNode().getTask(); } } if(task != null) { for(Node node : task.getInputNodes()) { File file = getOutputFileForNode(node); if(file != null){ inputNodeNumberToFilename.put(node.getNodeIndex(), file.getName()); } } System.out.println("in node to file : " + inputNodeNumberToFilename.toString()); for(Node node : task.getOutputNodes()) { File file = getOutputFileForNode(node); if(file != null) { outputNodeNumberToFilename.put(node.getNodeIndex(), file.getName()); } } System.out.println("out node to file : " + outputNodeNumberToFilename.toString()); } } private boolean firstTime = true; //Called to rebuild the executableNode objects after deserializing public void init(Task task) { // System.out.println("Task " + task + " init, for some reason."); if(firstTime) { firstTime = !firstTime; } else { System.out.println("\nSecond init, loading from serials"); executableNodes = new ArrayList<ExecutableNode>(); confirmWorkingDir(); System.out.println("in node to file : " + inputNodeNumberToFilename.toString()); System.out.println("out node to file : " + outputNodeNumberToFilename.toString()); for(Integer integer : inputNodeNumberToFilename.keySet()) { Node node = task.getInputNode(integer); if(node != null) { addExecutableNodeMapping(node, inputNodeNumberToFilename.get(integer)); } } for(Integer integer : outputNodeNumberToFilename.keySet()) { Node node = task.getOutputNode(integer); if(node != null) { addExecutableNodeMapping(node, outputNodeNumberToFilename.get(integer)); } } } } private void confirmWorkingDir() { if(workingDir == null || !workingDir.exists()) { System.out.println("Task " + taskName + " is missing."); if(!primaryExec.equals("")) { File file = new File(primaryExec); if(file.exists()) { workingDir = new File(file.getParent()); } } else { String userDir = System.getenv("user.dir"); if(userDir != null) { workingDir = new File(userDir); } } System.out.println("Working dir for " + taskName + " set to " + workingDir.getAbsolutePath()); } } private void addExecutableNode(ExecutableNode executableNode) { executableNodes.add(executableNode); updatedExeceutableNode(); System.out.println("Node added : " + executableNode); } public void addExecutableNodeMapping(Node node, String fileName) { System.out.println("\nnode, file"); boolean update = false; for(ExecutableNode executableNode : executableNodes){ if(executableNode.getNode() == node){ executableNode.setNode(node); executableNode.setFilename(fileName); update = true; } } if(!update){ addExecutableNode(new ExecutableNode(node, fileName)); } else { updatedExeceutableNode(); } } public void addExecutableNodeMapping(Node node, AbstractPort abstractPort) { System.out.println("\nnode, port"); boolean update = false; for(ExecutableNode executableNode : executableNodes){ if(executableNode.getNode() == node || executableNode.getAbstractPort() == abstractPort){ executableNode.setNode(node); executableNode.setAbstractPort(abstractPort); update = true; } } if(!update){ addExecutableNode(new ExecutableNode(node, abstractPort)); } else { updatedExeceutableNode(); } } public void addExecutableNodeMapping(AbstractPort abstractPort, String fileName) { System.out.println("\nport, name"); boolean update = false; for(ExecutableNode executableNode : executableNodes){ if(executableNode.getAbstractPort() == abstractPort){ executableNode.setFilename(fileName); executableNode.setAbstractPort(abstractPort); update = true; } } if(!update){ addExecutableNode(new ExecutableNode(abstractPort, fileName)); } else { updatedExeceutableNode(); } } public ArrayList<ExecutableNode> getInputNodes(){ return getExecutableNodes(true); } private ArrayList<ExecutableNode> getExecutableNodes(boolean inputs) { ArrayList<ExecutableNode> returning = new ArrayList<ExecutableNode>(); if(executableNodes == null){ executableNodes = new ArrayList<ExecutableNode>(); } for(ExecutableNode executableNode : executableNodes){ if(executableNode.getNode() != null){ if(executableNode.getNode().isInputNode() == inputs){ returning.add(executableNode); } } else if(executableNode.getAbstractPort() != null){ if(executableNode.getAbstractPort().isInputPort() == inputs){ returning.add(executableNode); } } } return returning; } public ArrayList<ExecutableNode> getOutputNodes(){ return getExecutableNodes(false); } public void removeExecutableNode(Node node) { ArrayList<ExecutableNode> removing = new ArrayList<ExecutableNode>(); for(ExecutableNode executableNode : executableNodes) { if(executableNode.getNode() == node) { removing.add(executableNode); } if(executableNode.getNode().getName().equals(node.getName())){ removing.add(executableNode); } } for(ExecutableNode executableNode : removing) { executableNodes.remove(executableNode); } updatedExeceutableNode(); } public ArrayList<File> getWorkingDirFileWhichAreNotInputsOrOutputs() { ArrayList<File> returnedFiles = new ArrayList<File>(); if(workingDir.exists() && workingDir.isDirectory()) { File[] files = workingDir.listFiles(); for(File file : files) { boolean add = !isInputOrOutput(file); if(add && file.isFile()) { System.out.println("Adding to bundle " + file.getAbsolutePath()); returnedFiles.add(file); } } } return returnedFiles; } private boolean isInputOrOutput(File file) { for(ExecutableNode executableNode : executableNodes) { String filename = executableNode.getFilename(); if(filename.equals(file.getName())){ return true; } } return false; } public String getArgsAsString() { String argstring = ""; for(String arg : args) { argstring += arg + " "; } return argstring; } }