From 88d3e743ec9b03a104be3408f141b5d2251d2227 Mon Sep 17 00:00:00 2001 From: John Patrick Date: Thu, 13 Sep 2018 22:57:55 +0100 Subject: [PATCH 1/4] Use ServiceLoader for ObjectFactory --- .../io/cucumber/guice/impl/GuiceFactory.java | 3 +- .../services/cucumber.api.java.ObjectFactory | 1 + .../java/cucumber/api/java/ObjectFactory.java | 1 + .../java/DefaultJavaObjectFactory.java | 4 +- .../io/cucumber/java/ObjectFactoryLoader.java | 53 +++++++++++-------- .../io/cucumber/needle/NeedleFactory.java | 5 +- .../services/cucumber.api.java.ObjectFactory | 1 + .../openejb/OpenEJBObjectFactory.java | 6 ++- .../services/cucumber.api.java.ObjectFactory | 1 + .../cucumber/picocontainer/PicoFactory.java | 5 +- .../services/cucumber.api.java.ObjectFactory | 1 + .../io/cucumber/spring/SpringFactory.java | 4 +- .../services/cucumber.api.java.ObjectFactory | 1 + .../java/io/cucumber/weld/WeldFactory.java | 4 +- .../services/cucumber.api.java.ObjectFactory | 1 + 15 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 guice/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory create mode 100644 needle/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory create mode 100644 openejb/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory create mode 100644 picocontainer/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory create mode 100644 spring/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory create mode 100644 weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory diff --git a/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java b/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java index ccf963db0b..2ec8b0fd1b 100644 --- a/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java +++ b/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java @@ -8,7 +8,8 @@ /** * Guice implementation of the cucumber.api.java.ObjectFactory. */ -public class GuiceFactory implements ObjectFactory { +public class GuiceFactory + implements ObjectFactory { private final Injector injector; diff --git a/guice/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/guice/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory new file mode 100644 index 0000000000..a88d454ca6 --- /dev/null +++ b/guice/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -0,0 +1 @@ +io.cucumber.guice.impl.GuiceFactory diff --git a/java/src/main/java/cucumber/api/java/ObjectFactory.java b/java/src/main/java/cucumber/api/java/ObjectFactory.java index 4b8a941dcd..9f1c08866b 100644 --- a/java/src/main/java/cucumber/api/java/ObjectFactory.java +++ b/java/src/main/java/cucumber/api/java/ObjectFactory.java @@ -32,4 +32,5 @@ public interface ObjectFactory { * @return new Glue instance of type T */ T getInstance(Class glueClass); + } diff --git a/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java b/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java index ea1bf2104f..c132ccfa88 100644 --- a/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java +++ b/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java @@ -11,7 +11,9 @@ * This class has package scope so it doesn't loadGlue loaded by reflection, * thereby colliding with other DI implementations. */ -class DefaultJavaObjectFactory implements ObjectFactory { +class DefaultJavaObjectFactory + implements ObjectFactory { + private final Map, Object> instances = new HashMap, Object>(); public void start() { diff --git a/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java b/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java index a83ab0cd53..d0049916a3 100644 --- a/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java +++ b/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java @@ -2,45 +2,55 @@ import cucumber.api.java.ObjectFactory; import io.cucumber.core.io.ClassFinder; -import io.cucumber.core.exception.CucumberException; -import io.cucumber.core.reflection.NoInstancesException; -import io.cucumber.core.reflection.Reflections; -import io.cucumber.core.reflection.TooManyInstancesException; -import static java.util.Arrays.asList; +import java.util.Iterator; +import java.util.ServiceLoader; public class ObjectFactoryLoader { + + private static final ServiceLoader LOADER = ServiceLoader.load(ObjectFactory.class); + private ObjectFactoryLoader() { } /** * Loads an instance of {@link ObjectFactory}. The class name can be explicit, or it can be null. - * When it's null, the implementation is searched for in the
cucumber.runtime
packahe. + * When it's null, the implementation is searched for in the
cucumber.runtime
package. * + * @deprecated as of version 4.0.0; use {@code loadObjectFactory() } instead. * @param classFinder where to load classes from * @param objectFactoryClassName specific class name of {@link ObjectFactory} implementation. May be null. * @return an instance of {@link ObjectFactory} */ + @Deprecated public static ObjectFactory loadObjectFactory(ClassFinder classFinder, String objectFactoryClassName) { + return loadObjectFactory(); + } + + /** + * Loads an instance of {@link ObjectFactory} using the {@link ServiceLoader}. + * The class name can be explicit, or it can be null. + * When it's null, the implementation is searched for in the
cucumber.runtime
package. + * + * @return an instance of {@link ObjectFactory} + */ + public static ObjectFactory loadObjectFactory() { + + final Iterator objectFactories = LOADER.iterator(); + ObjectFactory objectFactory; - try { - Reflections reflections = new Reflections(classFinder); - - if(objectFactoryClassName != null) { - Class objectFactoryClass = (Class) classFinder.loadClass(objectFactoryClassName); - objectFactory = reflections.newInstance(new Class[0], new Object[0], objectFactoryClass); - } else { - objectFactory = reflections.instantiateExactlyOneSubclass(ObjectFactory.class, asList("io.cucumber"), new Class[0], new Object[0], null); - } - } catch (TooManyInstancesException e) { - System.out.println(e.getMessage()); - System.out.println(getMultipleObjectFactoryLogMessage()); + if (objectFactories.hasNext()) { + objectFactory = objectFactories.next(); + + } else { objectFactory = new DefaultJavaObjectFactory(); - } catch (NoInstancesException e) { + } + + if (objectFactories.hasNext()) { + System.out.println(getMultipleObjectFactoryLogMessage()); objectFactory = new DefaultJavaObjectFactory(); - } catch (ClassNotFoundException e) { - throw new CucumberException("Couldn't instantiate custom ObjectFactory", e); } + return objectFactory; } @@ -53,4 +63,5 @@ private static String getMultipleObjectFactoryLogMessage() { sb.append("In order to enjoy IoC features, please remove the unnecessary dependencies from your classpath.\n"); return sb.toString(); } + } diff --git a/needle/src/main/java/io/cucumber/needle/NeedleFactory.java b/needle/src/main/java/io/cucumber/needle/NeedleFactory.java index 3d07ad86a4..614898ab53 100644 --- a/needle/src/main/java/io/cucumber/needle/NeedleFactory.java +++ b/needle/src/main/java/io/cucumber/needle/NeedleFactory.java @@ -14,7 +14,9 @@ /** * Needle factory for object resolution inside of cucumber tests. */ -public class NeedleFactory extends NeedleTestcase implements ObjectFactory { +public class NeedleFactory + extends NeedleTestcase + implements ObjectFactory { private final Map, Object> cachedStepsInstances = new LinkedHashMap, Object>(); private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -96,4 +98,5 @@ private T createStepsInstance(final Class type) throws Exception { static InjectionProvider[] setUpInjectionProviders(final String resourceName) { return new CucumberNeedleConfiguration(resourceName).getInjectionProviders(); } + } diff --git a/needle/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/needle/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory new file mode 100644 index 0000000000..fb070b0935 --- /dev/null +++ b/needle/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -0,0 +1 @@ +io.cucumber.needle.NeedleFactory diff --git a/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java b/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java index 54192bcd53..5a8cfe7573 100644 --- a/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java +++ b/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java @@ -12,7 +12,9 @@ import java.util.Map; import java.util.Properties; -public class OpenEJBObjectFactory implements ObjectFactory { +public class OpenEJBObjectFactory + implements ObjectFactory { + private final List classes = new ArrayList(); private final Map, Object> instances = new HashMap, Object>(); private EJBContainer container; @@ -60,5 +62,5 @@ public T getInstance(Class type) { instances.put(type, object); return object; } -} +} diff --git a/openejb/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/openejb/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory new file mode 100644 index 0000000000..f7f69708e0 --- /dev/null +++ b/openejb/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -0,0 +1 @@ +io.cucumber.openejb.OpenEJBObjectFactory diff --git a/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java b/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java index a11d9612b0..3a7e88aaa7 100644 --- a/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java +++ b/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java @@ -9,7 +9,9 @@ import java.util.HashSet; import java.util.Set; -public class PicoFactory implements ObjectFactory { +public class PicoFactory + implements ObjectFactory { + private MutablePicoContainer pico; private final Set> classes = new HashSet>(); @@ -47,4 +49,5 @@ private void addConstructorDependencies(Class clazz) { } } } + } diff --git a/picocontainer/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/picocontainer/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory new file mode 100644 index 0000000000..235a25f5d4 --- /dev/null +++ b/picocontainer/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -0,0 +1 @@ +io.cucumber.picocontainer.PicoFactory diff --git a/spring/src/main/java/io/cucumber/spring/SpringFactory.java b/spring/src/main/java/io/cucumber/spring/SpringFactory.java index ef4d50bd6d..f4f767b32c 100644 --- a/spring/src/main/java/io/cucumber/spring/SpringFactory.java +++ b/spring/src/main/java/io/cucumber/spring/SpringFactory.java @@ -59,7 +59,8 @@ * * */ -public class SpringFactory implements ObjectFactory { +public class SpringFactory + implements ObjectFactory { private ConfigurableListableBeanFactory beanFactory; private CucumberTestContextManager testContextManager; @@ -254,4 +255,5 @@ private void registerGlueCodeScope(ConfigurableApplicationContext context) { } while (context != null); } } + } diff --git a/spring/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/spring/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory new file mode 100644 index 0000000000..b7b15815b0 --- /dev/null +++ b/spring/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -0,0 +1 @@ +io.cucumber.spring.SpringFactory diff --git a/weld/src/main/java/io/cucumber/weld/WeldFactory.java b/weld/src/main/java/io/cucumber/weld/WeldFactory.java index 095a9623e0..033a7fb369 100644 --- a/weld/src/main/java/io/cucumber/weld/WeldFactory.java +++ b/weld/src/main/java/io/cucumber/weld/WeldFactory.java @@ -5,7 +5,8 @@ import org.jboss.weld.environment.se.Weld; import org.jboss.weld.environment.se.WeldContainer; -public class WeldFactory implements ObjectFactory { +public class WeldFactory + implements ObjectFactory { private WeldContainer containerInstance; @@ -53,4 +54,5 @@ public boolean addClass(Class clazz) { public T getInstance(Class type) { return containerInstance.select(type).get(); } + } diff --git a/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory new file mode 100644 index 0000000000..965281dd4b --- /dev/null +++ b/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -0,0 +1 @@ +io.cucumber.weld.WeldFactory \ No newline at end of file From 07121b3039b2d98ba33a94e12fa415623ae3514e Mon Sep 17 00:00:00 2001 From: John Patrick Date: Fri, 14 Sep 2018 15:03:32 +0100 Subject: [PATCH 2/4] Clean up my auto bad habbit of auto code formatting --- .../src/main/java/io/cucumber/guice/impl/GuiceFactory.java | 3 +-- java/src/main/java/cucumber/api/java/ObjectFactory.java | 1 - .../java/io/cucumber/java/DefaultJavaObjectFactory.java | 4 +--- .../src/main/java/io/cucumber/java/ObjectFactoryLoader.java | 3 +-- needle/src/main/java/io/cucumber/needle/NeedleFactory.java | 5 +---- .../main/java/io/cucumber/openejb/OpenEJBObjectFactory.java | 6 ++---- .../main/java/io/cucumber/picocontainer/PicoFactory.java | 5 +---- spring/src/main/java/io/cucumber/spring/SpringFactory.java | 5 +---- weld/src/main/java/io/cucumber/weld/WeldFactory.java | 4 +--- 9 files changed, 9 insertions(+), 27 deletions(-) diff --git a/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java b/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java index 2ec8b0fd1b..ccf963db0b 100644 --- a/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java +++ b/guice/src/main/java/io/cucumber/guice/impl/GuiceFactory.java @@ -8,8 +8,7 @@ /** * Guice implementation of the cucumber.api.java.ObjectFactory. */ -public class GuiceFactory - implements ObjectFactory { +public class GuiceFactory implements ObjectFactory { private final Injector injector; diff --git a/java/src/main/java/cucumber/api/java/ObjectFactory.java b/java/src/main/java/cucumber/api/java/ObjectFactory.java index 9f1c08866b..4b8a941dcd 100644 --- a/java/src/main/java/cucumber/api/java/ObjectFactory.java +++ b/java/src/main/java/cucumber/api/java/ObjectFactory.java @@ -32,5 +32,4 @@ public interface ObjectFactory { * @return new Glue instance of type T */ T getInstance(Class glueClass); - } diff --git a/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java b/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java index c132ccfa88..ea1bf2104f 100644 --- a/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java +++ b/java/src/main/java/io/cucumber/java/DefaultJavaObjectFactory.java @@ -11,9 +11,7 @@ * This class has package scope so it doesn't loadGlue loaded by reflection, * thereby colliding with other DI implementations. */ -class DefaultJavaObjectFactory - implements ObjectFactory { - +class DefaultJavaObjectFactory implements ObjectFactory { private final Map, Object> instances = new HashMap, Object>(); public void start() { diff --git a/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java b/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java index d0049916a3..d83eb034db 100644 --- a/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java +++ b/java/src/main/java/io/cucumber/java/ObjectFactoryLoader.java @@ -17,12 +17,11 @@ private ObjectFactoryLoader() { * Loads an instance of {@link ObjectFactory}. The class name can be explicit, or it can be null. * When it's null, the implementation is searched for in the
cucumber.runtime
package. * - * @deprecated as of version 4.0.0; use {@code loadObjectFactory() } instead. * @param classFinder where to load classes from * @param objectFactoryClassName specific class name of {@link ObjectFactory} implementation. May be null. * @return an instance of {@link ObjectFactory} */ - @Deprecated + // TODO remove once confirmed classFinder and/or objectFactoryClassName are not need for serviceLoader public static ObjectFactory loadObjectFactory(ClassFinder classFinder, String objectFactoryClassName) { return loadObjectFactory(); } diff --git a/needle/src/main/java/io/cucumber/needle/NeedleFactory.java b/needle/src/main/java/io/cucumber/needle/NeedleFactory.java index 614898ab53..3d07ad86a4 100644 --- a/needle/src/main/java/io/cucumber/needle/NeedleFactory.java +++ b/needle/src/main/java/io/cucumber/needle/NeedleFactory.java @@ -14,9 +14,7 @@ /** * Needle factory for object resolution inside of cucumber tests. */ -public class NeedleFactory - extends NeedleTestcase - implements ObjectFactory { +public class NeedleFactory extends NeedleTestcase implements ObjectFactory { private final Map, Object> cachedStepsInstances = new LinkedHashMap, Object>(); private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -98,5 +96,4 @@ private T createStepsInstance(final Class type) throws Exception { static InjectionProvider[] setUpInjectionProviders(final String resourceName) { return new CucumberNeedleConfiguration(resourceName).getInjectionProviders(); } - } diff --git a/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java b/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java index 5a8cfe7573..54192bcd53 100644 --- a/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java +++ b/openejb/src/main/java/io/cucumber/openejb/OpenEJBObjectFactory.java @@ -12,9 +12,7 @@ import java.util.Map; import java.util.Properties; -public class OpenEJBObjectFactory - implements ObjectFactory { - +public class OpenEJBObjectFactory implements ObjectFactory { private final List classes = new ArrayList(); private final Map, Object> instances = new HashMap, Object>(); private EJBContainer container; @@ -62,5 +60,5 @@ public T getInstance(Class type) { instances.put(type, object); return object; } - } + diff --git a/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java b/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java index 3a7e88aaa7..a11d9612b0 100644 --- a/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java +++ b/picocontainer/src/main/java/io/cucumber/picocontainer/PicoFactory.java @@ -9,9 +9,7 @@ import java.util.HashSet; import java.util.Set; -public class PicoFactory - implements ObjectFactory { - +public class PicoFactory implements ObjectFactory { private MutablePicoContainer pico; private final Set> classes = new HashSet>(); @@ -49,5 +47,4 @@ private void addConstructorDependencies(Class clazz) { } } } - } diff --git a/spring/src/main/java/io/cucumber/spring/SpringFactory.java b/spring/src/main/java/io/cucumber/spring/SpringFactory.java index f4f767b32c..3dbe4cfc3a 100644 --- a/spring/src/main/java/io/cucumber/spring/SpringFactory.java +++ b/spring/src/main/java/io/cucumber/spring/SpringFactory.java @@ -59,9 +59,7 @@ * * */ -public class SpringFactory - implements ObjectFactory { - +public class SpringFactory implements ObjectFactory { private ConfigurableListableBeanFactory beanFactory; private CucumberTestContextManager testContextManager; @@ -255,5 +253,4 @@ private void registerGlueCodeScope(ConfigurableApplicationContext context) { } while (context != null); } } - } diff --git a/weld/src/main/java/io/cucumber/weld/WeldFactory.java b/weld/src/main/java/io/cucumber/weld/WeldFactory.java index 033a7fb369..095a9623e0 100644 --- a/weld/src/main/java/io/cucumber/weld/WeldFactory.java +++ b/weld/src/main/java/io/cucumber/weld/WeldFactory.java @@ -5,8 +5,7 @@ import org.jboss.weld.environment.se.Weld; import org.jboss.weld.environment.se.WeldContainer; -public class WeldFactory - implements ObjectFactory { +public class WeldFactory implements ObjectFactory { private WeldContainer containerInstance; @@ -54,5 +53,4 @@ public boolean addClass(Class clazz) { public T getInstance(Class type) { return containerInstance.select(type).get(); } - } From 0741ed21854c6cd1d48156c9d2b735f69c16c8dd Mon Sep 17 00:00:00 2001 From: John Patrick Date: Fri, 14 Sep 2018 15:04:53 +0100 Subject: [PATCH 3/4] Clean up my auto bad habbit of auto code formatting --- spring/src/main/java/io/cucumber/spring/SpringFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring/src/main/java/io/cucumber/spring/SpringFactory.java b/spring/src/main/java/io/cucumber/spring/SpringFactory.java index 3dbe4cfc3a..ef4d50bd6d 100644 --- a/spring/src/main/java/io/cucumber/spring/SpringFactory.java +++ b/spring/src/main/java/io/cucumber/spring/SpringFactory.java @@ -60,6 +60,7 @@ * */ public class SpringFactory implements ObjectFactory { + private ConfigurableListableBeanFactory beanFactory; private CucumberTestContextManager testContextManager; From f7594f356da399d7ba28dda4c457f9a3c643673c Mon Sep 17 00:00:00 2001 From: John Patrick Date: Fri, 14 Sep 2018 15:06:03 +0100 Subject: [PATCH 4/4] new line as like other spi files --- .../resources/META-INF/services/cucumber.api.java.ObjectFactory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory b/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory index 965281dd4b..fb77476dd4 100644 --- a/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory +++ b/weld/src/main/resources/META-INF/services/cucumber.api.java.ObjectFactory @@ -1 +1 @@ -io.cucumber.weld.WeldFactory \ No newline at end of file +io.cucumber.weld.WeldFactory