All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cucumber.runtime.RuntimeOptions Maven / Gradle / Ivy

There is a newer version: 1.2.6
Show newest version
package cucumber.runtime;

import cucumber.api.SnippetType;
import cucumber.api.StepDefinitionReporter;
import cucumber.api.SummaryPrinter;
import cucumber.runtime.formatter.ColorAware;
import cucumber.runtime.formatter.PluginFactory;
import cucumber.runtime.formatter.StrictAware;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.model.CucumberFeature;
import cucumber.runtime.model.PathWithLines;
import gherkin.I18n;
import gherkin.formatter.Formatter;
import gherkin.formatter.Reporter;
import gherkin.util.FixJava;

import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.regex.Pattern;

import static cucumber.runtime.model.CucumberFeature.load;

// IMPORTANT! Make sure USAGE.txt is always uptodate if this class changes.
public class RuntimeOptions {
    public static final String VERSION = ResourceBundle.getBundle("cucumber.version").getString("cucumber-jvm.version");
    public static final String USAGE_RESOURCE = "/cucumber/api/cli/USAGE.txt";

    static String usageText;

    private final List glue = new ArrayList();
    private final List filters = new ArrayList();
    private final List featurePaths = new ArrayList();
    private final List pluginFormatterNames = new ArrayList();
    private final List pluginStepDefinitionReporterNames = new ArrayList();
    private final List pluginSummaryPrinterNames = new ArrayList();
    private final PluginFactory pluginFactory;
    private final List plugins = new ArrayList();
    private boolean dryRun;
    private boolean strict = false;
    private boolean monochrome = false;
    private SnippetType snippetType = SnippetType.UNDERSCORE;
    private boolean pluginNamesInstantiated;

    /**
     * Create a new instance from a string of options, for example:
     * 

* * * @param argv the arguments */ public RuntimeOptions(String argv) { this(new PluginFactory(), Shellwords.parse(argv)); } /** * Create a new instance from a list of options, for example: *

* * * @param argv the arguments */ public RuntimeOptions(List argv) { this(new PluginFactory(), argv); } public RuntimeOptions(Env env, List argv) { this(env, new PluginFactory(), argv); } public RuntimeOptions(PluginFactory pluginFactory, List argv) { this(Env.INSTANCE, pluginFactory, argv); } public RuntimeOptions(Env env, PluginFactory pluginFactory, List argv) { this.pluginFactory = pluginFactory; argv = new ArrayList(argv); // in case the one passed in is unmodifiable. parse(argv); String cucumberOptionsFromEnv = env.get("cucumber.options"); if (cucumberOptionsFromEnv != null) { parse(Shellwords.parse(cucumberOptionsFromEnv)); } if (pluginFormatterNames.isEmpty()) { pluginFormatterNames.add("progress"); } if (pluginSummaryPrinterNames.isEmpty()) { pluginSummaryPrinterNames.add("default_summary"); } } private void parse(List args) { List parsedFilters = new ArrayList(); List parsedFeaturePaths = new ArrayList(); List parsedGlue = new ArrayList(); while (!args.isEmpty()) { String arg = args.remove(0).trim(); if (arg.equals("--help") || arg.equals("-h")) { printUsage(); System.exit(0); } else if (arg.equals("--version") || arg.equals("-v")) { System.out.println(VERSION); System.exit(0); } else if (arg.equals("--i18n")) { String nextArg = args.remove(0); System.exit(printI18n(nextArg)); } else if (arg.equals("--glue") || arg.equals("-g")) { String gluePath = args.remove(0); parsedGlue.add(gluePath); } else if (arg.equals("--tags") || arg.equals("-t")) { parsedFilters.add(args.remove(0)); } else if (arg.equals("--plugin") || arg.equals("-p")) { addPluginName(args.remove(0)); } else if (arg.equals("--format") || arg.equals("-f")) { System.err.println("WARNING: Cucumber-JVM's --format option is deprecated. Please use --plugin instead."); addPluginName(args.remove(0)); } else if (arg.equals("--no-dry-run") || arg.equals("--dry-run") || arg.equals("-d")) { dryRun = !arg.startsWith("--no-"); } else if (arg.equals("--no-strict") || arg.equals("--strict") || arg.equals("-s")) { strict = !arg.startsWith("--no-"); } else if (arg.equals("--no-monochrome") || arg.equals("--monochrome") || arg.equals("-m")) { monochrome = !arg.startsWith("--no-"); } else if (arg.equals("--snippets")) { String nextArg = args.remove(0); snippetType = SnippetType.fromString(nextArg); } else if (arg.equals("--name") || arg.equals("-n")) { String nextArg = args.remove(0); Pattern patternFilter = Pattern.compile(nextArg); parsedFilters.add(patternFilter); } else if (arg.startsWith("-")) { printUsage(); throw new CucumberException("Unknown option: " + arg); } else { parsedFeaturePaths.add(arg); } } if (!parsedFilters.isEmpty() || haveLineFilters(parsedFeaturePaths)) { filters.clear(); filters.addAll(parsedFilters); if (parsedFeaturePaths.isEmpty() && !featurePaths.isEmpty()) { stripLinesFromFeaturePaths(featurePaths); } } if (!parsedFeaturePaths.isEmpty()) { featurePaths.clear(); featurePaths.addAll(parsedFeaturePaths); } if (!parsedGlue.isEmpty()) { glue.clear(); glue.addAll(parsedGlue); } } private void addPluginName(String name) { if (PluginFactory.isFormatterName(name)) { pluginFormatterNames.add(name); } else if (PluginFactory.isStepDefinitionResporterName(name)) { pluginStepDefinitionReporterNames.add(name); } else if (PluginFactory.isSummaryPrinterName(name)) { pluginSummaryPrinterNames.add(name); } else { throw new CucumberException("Unrecognized plugin: " + name); } } private boolean haveLineFilters(List parsedFeaturePaths) { for (String pathName : parsedFeaturePaths) { if (pathName.startsWith("@") || PathWithLines.hasLineFilters(pathName)) { return true; } } return false; } private void stripLinesFromFeaturePaths(List featurePaths) { List newPaths = new ArrayList(); for (String pathName : featurePaths) { newPaths.add(PathWithLines.stripLineFilters(pathName)); } featurePaths.clear(); featurePaths.addAll(newPaths); } private void printUsage() { loadUsageTextIfNeeded(); System.out.println(usageText); } static void loadUsageTextIfNeeded() { if (usageText == null) { try { Reader reader = new InputStreamReader(FixJava.class.getResourceAsStream(USAGE_RESOURCE), "UTF-8"); usageText = FixJava.readReader(reader); } catch (Exception e) { usageText = "Could not load usage text: " + e.toString(); } } } private int printI18n(String language) { List all = I18n.getAll(); if (language.equalsIgnoreCase("help")) { for (I18n i18n : all) { System.out.println(i18n.getIsoCode()); } return 0; } else { return printKeywordsFor(language, all); } } private int printKeywordsFor(String language, List all) { for (I18n i18n : all) { if (i18n.getIsoCode().equalsIgnoreCase(language)) { System.out.println(i18n.getKeywordTable()); return 0; } } System.err.println("Unrecognised ISO language code"); return 1; } public List cucumberFeatures(ResourceLoader resourceLoader) { return load(resourceLoader, featurePaths, filters, System.out); } List getPlugins() { if (!pluginNamesInstantiated) { for (String pluginName : pluginFormatterNames) { Object plugin = pluginFactory.create(pluginName); plugins.add(plugin); setMonochromeOnColorAwarePlugins(plugin); setStrictOnStrictAwarePlugins(plugin); } for (String pluginName : pluginStepDefinitionReporterNames) { Object plugin = pluginFactory.create(pluginName); plugins.add(plugin); } for (String pluginName : pluginSummaryPrinterNames) { Object plugin = pluginFactory.create(pluginName); plugins.add(plugin); } pluginNamesInstantiated = true; } return plugins; } public Formatter formatter(ClassLoader classLoader) { return pluginProxy(classLoader, Formatter.class); } public Reporter reporter(ClassLoader classLoader) { return pluginProxy(classLoader, Reporter.class); } public StepDefinitionReporter stepDefinitionReporter(ClassLoader classLoader) { return pluginProxy(classLoader, StepDefinitionReporter.class); } public SummaryPrinter summaryPrinter(ClassLoader classLoader) { return pluginProxy(classLoader, SummaryPrinter.class); } /** * Creates a dynamic proxy that multiplexes method invocations to all plugins of the same type. * * @param classLoader used to create the proxy * @param type proxy type * @param generic proxy type * @return a proxy */ public T pluginProxy(ClassLoader classLoader, final Class type) { Object proxy = Proxy.newProxyInstance(classLoader, new Class[]{type}, new InvocationHandler() { @Override public Object invoke(Object target, Method method, Object[] args) throws Throwable { for (Object plugin : getPlugins()) { if (type.isInstance(plugin)) { try { Utils.invoke(plugin, method, 0, args); } catch (Throwable t) { if (!method.getName().equals("startOfScenarioLifeCycle") && !method.getName().equals("endOfScenarioLifeCycle")) { // IntelliJ has its own formatter which doesn't yet implement these methods. throw t; } } } } return null; } }); return type.cast(proxy); } private void setMonochromeOnColorAwarePlugins(Object plugin) { if (plugin instanceof ColorAware) { ColorAware colorAware = (ColorAware) plugin; colorAware.setMonochrome(monochrome); } } private void setStrictOnStrictAwarePlugins(Object plugin) { if (plugin instanceof StrictAware) { StrictAware strictAware = (StrictAware) plugin; strictAware.setStrict(strict); } } public List getGlue() { return glue; } public boolean isStrict() { return strict; } public boolean isDryRun() { return dryRun; } public List getFeaturePaths() { return featurePaths; } public void addPlugin(Object plugin) { plugins.add(plugin); } public List getFilters() { return filters; } public boolean isMonochrome() { return monochrome; } public SnippetType getSnippetType() { return snippetType; } }