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

cucumber.runtime.formatter.PluginFactory Maven / Gradle / Ivy

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

import cucumber.runtime.CucumberException;
import cucumber.runtime.io.URLOutputStream;
import cucumber.runtime.io.UTF8OutputStreamWriter;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cucumber.runtime.Utils.toURL;
import static java.util.Arrays.asList;

/**
 * This class creates plugin instances from a String.
 * 

* The String is of the form name[:output] where name is either a fully qualified class name or one of the built-in short names. * output is optional for some plugin (and mandatory for some) and must refer to a path on the file system. *

* The plugin class must have a constructor that is either empty or takes a single argument of one of the following types: *

    *
  • {@link Appendable}
  • *
  • {@link File}
  • *
  • {@link URL}
  • *
  • {@link URI}
  • *
* Plugins must implement one of the following interfaces: *
    *
  • {@link gherkin.formatter.Formatter}
  • *
  • {@link gherkin.formatter.Reporter}
  • *
  • {@link cucumber.api.StepDefinitionReporter}
  • *
*/ public class PluginFactory { private final Class[] CTOR_ARGS = new Class[]{null, Appendable.class, URI.class, URL.class, File.class}; private static final Map PLUGIN_CLASSES = new HashMap() {{ put("null", NullFormatter.class); put("junit", JUnitFormatter.class); put("html", HTMLFormatter.class); put("pretty", CucumberPrettyFormatter.class); put("progress", ProgressFormatter.class); put("json", CucumberJSONFormatter.class); put("usage", UsageFormatter.class); put("rerun", RerunFormatter.class); }}; private static final Pattern PLUGIN_WITH_FILE_PATTERN = Pattern.compile("([^:]+):(.*)"); private String defaultOutFormatter = null; private Appendable defaultOut = new PrintStream(System.out) { @Override public void close() { // We have no intention to close System.out } }; public Object create(String pluginString) { Matcher pluginWithFile = PLUGIN_WITH_FILE_PATTERN.matcher(pluginString); String pluginName; String path = null; if (pluginWithFile.matches()) { pluginName = pluginWithFile.group(1); path = pluginWithFile.group(2); } else { pluginName = pluginString; } Class pluginClass = pluginClass(pluginName); try { return instantiate(pluginString, pluginClass, path); } catch (IOException e) { throw new CucumberException(e); } catch (URISyntaxException e) { throw new CucumberException(e); } } private T instantiate(String pluginString, Class pluginClass, String pathOrUrl) throws IOException, URISyntaxException { for (Class ctorArgClass : CTOR_ARGS) { Constructor constructor = findConstructor(pluginClass, ctorArgClass); if (constructor != null) { Object ctorArg = convertOrNull(pathOrUrl, ctorArgClass, pluginString); try { if (ctorArgClass == null) { return constructor.newInstance(); } else { if (ctorArg == null) { throw new CucumberException(String.format("You must supply an output argument to %s. Like so: %s:output", pluginString, pluginString)); } return constructor.newInstance(ctorArg); } } catch (InstantiationException e) { throw new CucumberException(e); } catch (IllegalAccessException e) { throw new CucumberException(e); } catch (InvocationTargetException e) { throw new CucumberException(e.getTargetException()); } } } throw new CucumberException(String.format("%s must have a constructor that is either empty or a single arg of one of: %s", pluginClass, asList(CTOR_ARGS))); } private Object convertOrNull(String pathOrUrl, Class ctorArgClass, String formatterString) throws IOException, URISyntaxException { if (ctorArgClass == null) { return null; } if (ctorArgClass.equals(URI.class)) { if (pathOrUrl != null) { return new URI(pathOrUrl); } } if (ctorArgClass.equals(URL.class)) { if (pathOrUrl != null) { return toURL(pathOrUrl); } } if (ctorArgClass.equals(File.class)) { if (pathOrUrl != null) { return new File(pathOrUrl); } } if (ctorArgClass.equals(Appendable.class)) { if (pathOrUrl != null) { return new UTF8OutputStreamWriter(new URLOutputStream(toURL(pathOrUrl))); } else { return defaultOutOrFailIfAlreadyUsed(formatterString); } } return null; } private Constructor findConstructor(Class pluginClass, Class ctorArgClass) { try { if (ctorArgClass == null) { return pluginClass.getConstructor(); } else { return pluginClass.getConstructor(ctorArgClass); } } catch (NoSuchMethodException e) { return null; } } private Class pluginClass(String pluginName) { Class pluginClass = (Class) PLUGIN_CLASSES.get(pluginName); if (pluginClass == null) { pluginClass = loadClass(pluginName); } return pluginClass; } @SuppressWarnings("unchecked") private Class loadClass(String className) { try { return (Class) Thread.currentThread().getContextClassLoader().loadClass(className); } catch (ClassNotFoundException e) { throw new CucumberException("Couldn't load plugin class: " + className, e); } } private Appendable defaultOutOrFailIfAlreadyUsed(String formatterString) { try { if (defaultOut != null) { defaultOutFormatter = formatterString; return defaultOut; } else { throw new CucumberException("Only one formatter can use STDOUT, now both " + defaultOutFormatter + " and " + formatterString + " use it. " + "If you use more than one formatter you must specify output path with PLUGIN:PATH_OR_URL"); } } finally { defaultOut = null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy