package org.trianacode.shiwaall.bundle; import org.apache.commons.logging.Log; import org.trianacode.annotation.CustomGUIComponent; import org.trianacode.annotation.Process; import org.trianacode.annotation.TextFieldParameter; import org.trianacode.annotation.Tool; import org.trianacode.enactment.StreamToOutput; import org.trianacode.enactment.logging.Loggers; import org.trianacode.enactment.logging.stampede.StampedeLog; import org.trianacode.shiwaall.utils.BrokerUtils; import org.trianacode.taskgraph.Task; import org.trianacode.taskgraph.annotation.TaskConscious; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; // TODO: Auto-generated Javadoc //import org.shiwa.desktop.data.util.DataUtils; /** * Created by IntelliJ IDEA. * User: Ian Harvey * Date: Aug 19, 2010 * Time: 11:08:09 AM * To change this template use File | Settings | File Templates. */ @Tool public class BundleToLocalTriana implements TaskConscious { /** The executable string. */ @TextFieldParameter private String executableString = ""; /** The runtime directory. */ @TextFieldParameter private String runtimeDirectory = ""; /** The concurrent processes. */ @TextFieldParameter private String concurrentProcesses = ""; /** The running processes. */ private int runningProcesses = 0; /** The return codes. */ ConcurrentHashMap<Integer, returnCode> returnCodes;// = new ConcurrentHashMap<Integer, returnCode>(); /** The Constant EXIT_CODE. */ private static final String EXIT_CODE = "exitCode"; /** * The Enum returnCode. */ enum returnCode { /** The success. */ SUCCESS, /** The fail. */ FAIL } /** The task. */ private Task task; /** * Process. * * @param list the list * @return the concurrent hash map * @throws Exception the exception */ @Process(gather = true) public ConcurrentHashMap<Integer, returnCode> process(List list) throws Exception { ArrayList<String> executableStrings = new ArrayList<String>(); executableString = execField.getText(); if (!executableString.equals("")) { executableStrings.add(executableString); } for (Object object : list) { if (object instanceof String[]) { Collections.addAll(executableStrings, (String[]) object); } else if (object instanceof String) { executableStrings.add((String) object); } } runtimeDirectory = runtimeField.getText(); if (runtimeDirectory == null || runtimeDirectory.equals("")) { runtimeDirectory = "."; } String concurrent = concurrentField.getText(); int allowedProcesses; if (concurrent != null) { if (concurrent.equals("")) { allowedProcesses = 1; } else { allowedProcesses = Integer.parseInt(concurrent); } } else { allowedProcesses = 1; } int run = 0; System.out.println(executableStrings.size() + " processes to run."); System.out.println("Allowing " + allowedProcesses + " concurrent processes."); returnCodes = new ConcurrentHashMap<Integer, returnCode>(); while (run < executableStrings.size()) { if (runningProcesses < allowedProcesses) { System.out.println("Beginning run " + run); String exec = executableStrings.get(run); System.out.println("Run " + run + ", executing : " + exec); StringExecutor executor = new StringExecutor(exec, new File(runtimeDirectory), run); executor.addPropertyChangeListener(new ExitCodeListener(run)); executor.execute(); run++; } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } int wait = 0; int time = 0; while (returnCodes.size() < executableStrings.size()) { if (wait > 10000) { time += 10; System.out.println(returnCodes.size() + "/" + executableStrings.size() + " complete. " + "~" + time + " seconds past." ); wait = 0; } try { Thread.sleep(1000); wait += 1000; } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(returnCodes.size() + " return codes recorded " + returnCodes.values().toString()); return returnCodes; } /** * The Class StringExecutor. */ class StringExecutor extends SwingWorker<Void, Void> { /** The exec string. */ private String execString; /** The exec location. */ private File execLocation; /** The run id. */ private int runID; /** * Instantiates a new string executor. * * @param execString the exec string * @param execLocation the exec location * @param runID the run id */ public StringExecutor(String execString, File execLocation, int runID) { this.execString = execString; this.execLocation = execLocation; this.runID = runID; } /* (non-Javadoc) * @see javax.swing.SwingWorker#doInBackground() */ @Override protected Void doInBackground() throws Exception { runningProcesses++; String exitCode = String.valueOf(executeProcess(execString, execLocation)); this.getPropertyChangeSupport().firePropertyChange(EXIT_CODE, null, exitCode); return null; } /* (non-Javadoc) * @see javax.swing.SwingWorker#done() */ public void done() { System.out.println("Finished " + this.runID); runningProcesses--; } /** * Execute process. * * @param executableString the executable string * @param execLocation the exec location * @return the int */ private int executeProcess(String executableString, File execLocation) { List<String> options = new ArrayList<String>(); String[] optionsStrings = executableString.split(" "); Collections.addAll(options, optionsStrings); try { String bundlePath = optionsStrings[4]; ShiwaBundleHelper shiwaBundleHelper = new ShiwaBundleHelper(bundlePath); BrokerUtils.prepareSubworkflow( task, UUID.randomUUID(), shiwaBundleHelper.getWorkflowImplementation() ); File temp = File.createTempFile("anything", "tmp"); shiwaBundleHelper.bundle(temp); // DataUtils.bundle( // temp, // shiwaBundleHelper.getWorkflowImplementation()); optionsStrings[4] = temp.getAbsolutePath(); } catch (Exception e) { e.printStackTrace(); } java.lang.Process process = null; try { ProcessBuilder processBuilder = new ProcessBuilder(optionsStrings); processBuilder.directory(execLocation); System.out.println(processBuilder.directory().getAbsolutePath()); process = processBuilder.start(); new StreamToOutput(process.getInputStream(), "std.out").start(); new StreamToOutput(process.getErrorStream(), "err").start(); return process.waitFor(); } catch (Exception except) { except.printStackTrace(); this.cancel(true); } return 1; } } /** * Log. * * @param s the s */ private void log(String s) { Log log = Loggers.DEV_LOGGER; log.debug(s); System.out.println(s); } /** The exec field. */ JTextField execField = new JTextField(""); /** The runtime field. */ JTextField runtimeField = new JTextField(""); ///Users/ian/Work/testBundles/DART"); /** The concurrent field. */ JTextField concurrentField = new JTextField(""); /** The main panel. */ private JPanel mainPanel; /** * Gets the component. * * @return the component */ @CustomGUIComponent public Component getComponent() { mainPanel = new JPanel(); getParams(); mainPanel.setLayout(new BorderLayout(5, 5)); JPanel topPanel = new JPanel(new GridLayout(0, 2, 5, 5)); JLabel execLabel = new JLabel("Executable string : "); JLabel folderLabel = new JLabel("Runtime folder : "); JLabel concurrentExecutionsLabel = new JLabel("Concurrent executions : "); topPanel.add(execLabel); topPanel.add(execField); topPanel.add(folderLabel); topPanel.add(runtimeField); topPanel.add(concurrentExecutionsLabel); topPanel.add(concurrentField); mainPanel.add(topPanel, BorderLayout.NORTH); JPanel lowerPanel = new JPanel(new GridLayout(0, 2, 5, 5)); JButton helpButton = new JButton("Help"); helpButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new helpFrame(); } }); JButton okButton = new JButton("Set"); helpButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { apply(); } }); lowerPanel.add(okButton); lowerPanel.add(helpButton); mainPanel.add(lowerPanel, BorderLayout.SOUTH); return mainPanel; } /** * Apply clicked. */ public void applyClicked() { apply(); } /** * Ok clicked. */ public void okClicked() { apply(); } /** * Apply. */ public void apply() { task.setParameter("executable", execField.getText() == null ? "" : execField.getText()); task.setParameter("runtimeDirectory", runtimeField.getText() == null ? "" : runtimeField.getText()); task.setParameter("concurrentProcesses", concurrentField.getText()); } /** * Gets the params. * * @return the params */ private void getParams() { executableString = (String) task.getParameter("executable"); execField.setText(executableString); runtimeDirectory = (String) task.getParameter("runtimeDirectory"); runtimeField.setText(runtimeDirectory); concurrentProcesses = (String) task.getParameter("concurrentProcesses"); concurrentField.setText(concurrentProcesses); } /* (non-Javadoc) * @see org.trianacode.taskgraph.annotation.TaskConscious#setTask(org.trianacode.taskgraph.Task) */ @Override public void setTask(Task task) { this.task = task; task.setParameter(StampedeLog.STAMPEDE_TASK_TYPE, StampedeLog.JobType.dax.desc); getParams(); } /** * The Class helpFrame. */ class helpFrame extends JFrame { /** * Instantiates a new help frame. */ public helpFrame() { this.setTitle("Help"); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); JLabel helpLabel = new JLabel("This is helpful"); JTextArea helpArea = new JTextArea("Executable String is a line of text which will be run in a process " + "\n\nRuntime folder is the location which the process will be run." + "\n\nConcurrent executions is the number of processes which will run at the same time. If the " + "input array has multiple strings to run, then this number dictates how many to do at the same time. " + "Once a process finishes, another starts till they are all complete." ); helpArea.setEditable(false); helpArea.setLineWrap(true); helpArea.setWrapStyleWord(true); JScrollPane scrollPane = new JScrollPane(helpArea); panel.add(helpLabel); panel.add(scrollPane); JButton ok = new JButton("Ok"); ok.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); panel.add(ok); this.add(panel); this.setSize(400, 200); this.setVisible(true); } } /** * The listener interface for receiving exitCode events. * The class that is interested in processing a exitCode * event implements this interface, and the object created * with that class is registered with a component using the * component's <code>addExitCodeListener<code> method. When * the exitCode event occurs, that object's appropriate * method is invoked. * * @see ExitCodeEvent */ private class ExitCodeListener implements PropertyChangeListener { /** The run id. */ private Integer runID; /** * Instantiates a new exit code listener. * * @param runID the run id */ public ExitCodeListener(int runID) { this.runID = runID; } /* (non-Javadoc) * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) */ @Override public void propertyChange(PropertyChangeEvent propertyChangeEvent) { Object returned = propertyChangeEvent.getNewValue(); if (returned instanceof String) { System.out.println("Run " + runID + " returned " + returned); String code = (String) returned; if (code.equals("0")) { returnCodes.put(runID, returnCode.SUCCESS); } else { returnCodes.put(runID, returnCode.FAIL); } } } } }