org.eclipse.emf.mwe.core.WorkflowRunner.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.emf.mwe.core.WorkflowRunner.java

Source

/*******************************************************************************
 * Copyright (c) 2005 - 2009 committers of openArchitectureWare and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     committers of openArchitectureWare - initial API and implementation
 *******************************************************************************/
package org.eclipse.emf.mwe.core;

import java.lang.reflect.Method;
import java.net.URL;
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.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
import org.eclipse.emf.mwe.core.monitor.ProgressMonitor2;
import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor;

/**
 * Main class to run a workflow.
 * <p>
 * Arguments:
 * <ul>
 * <li>Workflow configuration filename.
 * <li>an optional ProgressMonitor
 * <li>optional runtime properties that override those in workflow files
 * </ul>
 * 
 */
public class WorkflowRunner {

    private static final String PARAM = "p";

    private static final String MONITOR = "m";

    private static final String ANT = "a";

    private static final String CMDL = "c";

    private static final String ENGINE = "e";

    /**
     * Starts a workflow.
     * 
     * @param args
     *            Program arguments. See class documentation.
     */
    public static void main(final String[] args) throws Exception {
        // workaround for MacOSX classloader issue
        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=211167
        // if omitted, "Run as MWE workflow" action immediately terminates when
        // SWT libraries are in the classpath
        new Object();
        // end workaround

        CommandLine line = getCommandLine(args);
        boolean success = new WorkflowRunner().doRun(line, args);

        if (!success && line.hasOption(ANT)) {
            System.exit(1);
        }
    }

    @Deprecated
    public boolean run(final String workFlowFile, final ProgressMonitor theMonitor,
            final Map<String, String> theParams, final Map<String, ?> externalSlotContents) {
        return new WorkflowEngine().run(workFlowFile, theMonitor, theParams, externalSlotContents);
    }

    public boolean doRun(String[] progArgs, boolean debugMode, int port) throws Exception {
        WorkflowEngine runner = new WorkflowEngine();
        ProgressMonitor monitor = null;
        if (debugMode) {
            monitor = new DebugMonitor();
            ((DebugMonitor) monitor).init(port);
        }

        Map<String, String> params = new HashMap<String, String>();
        return runner.run(progArgs[0], monitor, params, null);
    }

    public boolean doRun(CommandLine line, String[] args) throws Exception {
        WorkflowEngine runner = new WorkflowEngine();
        if (line.hasOption(ENGINE)) {
            try {
                runner = (WorkflowEngine) Class.forName(line.getOptionValue(ENGINE)).newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        Map<String, String> params = new HashMap<String, String>();
        String wfFile = null;
        final String[] monitorOptValues = line.getOptionValues(MONITOR);

        if (line.hasOption(CMDL)) {
            // removed option --cmdLineProcessor
            final List<String> unprocessedArgs = new ArrayList<String>();
            for (int i = 0; i < args.length; i++) {
                final String arg = args[i];
                if (arg.equals("-" + CMDL) || arg.equals("--cmdLineProcessor")) {
                    i++; // ignore this and next element
                } else if (arg.equals("-" + MONITOR) || arg.equals("--monitorClass")) {
                    // i++; // ignore this and next element
                    i = i + monitorOptValues.length;
                } else if (arg.endsWith(".oaw") || arg.endsWith(".mwe")) {
                    if (wfFile != null) {
                        throw new IllegalStateException("Workflow file already defined as '" + wfFile + "'!");
                    }
                    wfFile = arg;
                    // continue the loop (will be handled later)
                } else {
                    unprocessedArgs.add(arg);
                }
            }

            final Class<?> cmdLineProcessor = ResourceLoaderFactory.createResourceLoader()
                    .loadClass(line.getOptionValue(CMDL));
            if (cmdLineProcessor == null) {
                throw new IllegalStateException(
                        "cannot find class '" + line.getOptionValue(CMDL) + "' for command line processing.");
            }
            final Method method = cmdLineProcessor.getMethod("processCmdLine", String[].class, Map.class,
                    WorkflowContext.class);
            method.invoke(cmdLineProcessor.newInstance(), unprocessedArgs.toArray(new String[0]), params,
                    runner.getContext());
        } else {
            params = resolveParams(line.getOptionValues(PARAM));
            wfFile = line.getArgs()[0];
        }

        if ((wfFile == null) || !(wfFile.endsWith(".oaw") || wfFile.endsWith(".mwe"))) {
            wrongCall(line);
            return false;
        }

        ProgressMonitor monitor = null;

        if (monitorOptValues != null) {
            final Class<?> clazz = ResourceLoaderFactory.createResourceLoader().loadClass(monitorOptValues[0]);
            if (clazz == null) {
                throw new ClassNotFoundException("Didn't find class " + monitorOptValues[0]);
            }
            monitor = (ProgressMonitor) clazz.newInstance();
            if (monitor instanceof ProgressMonitor2) {
                ((ProgressMonitor2) monitor).init(monitorOptValues);
            } else if (monitor instanceof DebugMonitor) {
                // this complication is because of an API problem.
                // debug monitor throws an IOException and is not 
                // compatible with ProgressMonitor2 interface.
                ((DebugMonitor) monitor).init(monitorOptValues);
            }
        }

        // normalize wfFile name so that it can be found in the class path
        // (necessary for debugger source lookup)
        URL wfUrl;
        int index = 0;
        do {
            wfUrl = ResourceLoaderFactory.createResourceLoader().getResource(wfFile);
            if (wfUrl == null) {
                index = wfFile.indexOf('/');
                if (index >= 0) {
                    wfFile = wfFile.substring(index + 1);
                }
            }
        } while ((wfUrl == null) && (index >= 0));

        if (wfUrl == null) {
            String msg = "can't find the workflow file '" + line.getArgs()[0] + "' in the current class path";
            throw new IllegalStateException(msg);
        }

        return runner.run(wfFile, monitor, params, null);
    }

    @SuppressWarnings("static-access")
    protected static CommandLine getCommandLine(String[] args) throws ParseException {
        final Options options = new Options();

        options.addOption(OptionBuilder.hasArgs().withArgName("className,moreArgs").withDescription(
                "the name of a class that implements ProgressMonitor. More arguments can be appended that will be injected to the monitor,"
                        + " if it has a init(String[] args) method.")
                .withLongOpt("monitorClass").withValueSeparator(',').create(MONITOR));

        options.addOption(OptionBuilder.withLongOpt("ant").withDescription("must be set when using in Ant context")
                .create(ANT));

        final Option paramOption = OptionBuilder.withArgName("key=value")
                .withDescription("external property that is handled as workflow property").hasArgs().create(PARAM);
        paramOption.setLongOpt("param");
        options.addOption(paramOption);

        options.addOption(OptionBuilder.hasArgs().withArgName("className").withDescription(
                "the name of a class that implements a public method 'public void processCmdLine(String[] cmdLineArgs, Map paramsToUseInWorkflow, WorkflowContext ctx)'.")
                .withLongOpt("cmdLineProcessor").create(CMDL));

        final Option runnerOption = OptionBuilder.withArgName("className")
                .withDescription("WorkflowRunnerEngine class").hasArgs().create(ENGINE);
        runnerOption.setLongOpt("engine");
        options.addOption(runnerOption);

        // create the parser
        final CommandLineParser parser = new PosixParser();
        CommandLine line = parser.parse(options, args);
        return line;
    }

    /**
     * Convert type line arguments into a hashmap. Each parameter is expected in format -pkey=value
     * 
     * @param args
     *            Program arguments
     * @return A map containing all identified parameters
     */
    protected Map<String, String> resolveParams(final String[] args) {
        final Map<String, String> params = new HashMap<String, String>();
        if (args == null) {
            return params;
        }
        for (final String element : args) {
            final String[] string = element.split("=", 2);
            if (string.length != 2) {
                throw new IllegalArgumentException("wrong param syntax (-pkey=value). was : " + element);
            }
            params.put(string[0], string[1]);
        }
        return params;
    }

    /**
     * Print usage information and terminate the program.
     * 
     * @param options
     */
    protected void wrongCall(final CommandLine line) {
        Options options = new Options();
        for (Option o : line.getOptions())
            options.addOption(o);
        final HelpFormatter formatter = new HelpFormatter();
        formatter
                .printHelp("java " + WorkflowRunner.class.getName() + " some_workflow_file.mwe [options]\nor\njava "
                        + WorkflowRunner.class.getName() + " some_workflow_file.oaw [options]\n", options);
        System.exit(0);
    }

}