13
13
import java .util .List ;
14
14
15
15
import static java .util .Arrays .asList ;
16
+ import java .util .Collection ;
17
+ import java .util .HashSet ;
18
+ import java .util .Iterator ;
19
+ import java .util .Objects ;
20
+ import java .util .ServiceLoader ;
16
21
17
- public class ObjectFactoryLoader {
22
+ public final class ObjectFactoryLoader {
18
23
19
- private static final Logger log = LoggerFactory .getLogger (ObjectFactoryLoader .class );
24
+ private static final Logger LOG = LoggerFactory .getLogger (ObjectFactoryLoader .class );
20
25
21
26
private ObjectFactoryLoader () {
22
27
}
@@ -30,27 +35,50 @@ private ObjectFactoryLoader() {
30
35
* @return an instance of {@link ObjectFactory}
31
36
*/
32
37
public static ObjectFactory loadObjectFactory (ClassFinder classFinder , String objectFactoryClassName ) {
33
- ObjectFactory objectFactory ;
34
38
try {
35
- Reflections reflections = new Reflections (classFinder );
36
-
37
- if (objectFactoryClassName != null ) {
38
- Class <ObjectFactory > objectFactoryClass = (Class <ObjectFactory >) classFinder .loadClass (objectFactoryClassName );
39
- objectFactory = reflections .newInstance (new Class [0 ], new Object [0 ], objectFactoryClass );
39
+ final Reflections reflections = new Reflections (classFinder );
40
+ if (objectFactoryClassName == null ) {
41
+ return loadSingleObjectFactory (reflections );
40
42
} else {
41
- List <URI > packages = asList (URI .create ("classpath:cucumber/runtime" ));
42
- objectFactory = reflections .instantiateExactlyOneSubclass (ObjectFactory .class , packages , new Class [0 ], new Object [0 ], null );
43
+ return loadSelectedObjectFactory (reflections , classFinder , objectFactoryClassName );
43
44
}
44
45
} catch (TooManyInstancesException e ) {
45
- log .warn (e .getMessage ());
46
- log .warn (getMultipleObjectFactoryLogMessage ());
47
- objectFactory = new DefaultJavaObjectFactory ();
46
+ LOG .warn (e .getMessage ());
47
+ LOG .warn (getMultipleObjectFactoryLogMessage ());
48
+ return new DefaultJavaObjectFactory ();
48
49
} catch (NoInstancesException e ) {
49
- objectFactory = new DefaultJavaObjectFactory ();
50
+ return new DefaultJavaObjectFactory ();
50
51
} catch (ClassNotFoundException e ) {
51
52
throw new CucumberException ("Couldn't instantiate custom ObjectFactory" , e );
52
53
}
53
- return objectFactory ;
54
+ }
55
+
56
+ private static ObjectFactory loadSingleObjectFactory (final Reflections reflections ) {
57
+ Iterator <io .cucumber .core .backend .ObjectFactory > serviceLoaderObjectFactories = ServiceLoader .load (io .cucumber .core .backend .ObjectFactory .class ).iterator ();
58
+ if (serviceLoaderObjectFactories .hasNext ()) {
59
+ final Collection <io .cucumber .core .backend .ObjectFactory > instances = new HashSet <>();
60
+ do {
61
+ instances .add (serviceLoaderObjectFactories .next ());
62
+ } while (serviceLoaderObjectFactories .hasNext ());
63
+ if (instances .size () > 1 ) {
64
+ throw new TooManyInstancesException (instances );
65
+ }
66
+ return new ObjectFactoryAdapter (instances .iterator ().next ());
67
+ } else {
68
+ LOG .warn ("Use deprecated reflections to load ObjectFactory." );
69
+ final List <URI > packages = asList (URI .create ("classpath:cucumber/runtime" ));
70
+ return reflections .instantiateExactlyOneSubclass (ObjectFactory .class , packages , new Class [0 ], new Object [0 ], null );
71
+ }
72
+ }
73
+
74
+ private static ObjectFactory loadSelectedObjectFactory (final Reflections reflections , final ClassFinder classFinder , final String objectFactoryClassName ) throws ClassNotFoundException {
75
+ final Iterator <? extends io .cucumber .core .backend .ObjectFactory > serviceLoaderObjectFactories = ServiceLoader .load (classFinder .<io .cucumber .core .backend .ObjectFactory >loadClass (objectFactoryClassName )).iterator ();
76
+ if (serviceLoaderObjectFactories .hasNext ()) {
77
+ return new ObjectFactoryAdapter (serviceLoaderObjectFactories .next ());
78
+ } else {
79
+ LOG .warn ("Use deprecated reflections to load requested ObjectFactory." );
80
+ return reflections .newInstance (new Class [0 ], new Object [0 ], classFinder .<ObjectFactory >loadClass (objectFactoryClassName ));
81
+ }
54
82
}
55
83
56
84
private static String getMultipleObjectFactoryLogMessage () {
@@ -62,4 +90,35 @@ private static String getMultipleObjectFactoryLogMessage() {
62
90
sb .append ("In order to enjoy IoC features, please remove the unnecessary dependencies from your classpath.\n " );
63
91
return sb .toString ();
64
92
}
93
+
94
+ private static class ObjectFactoryAdapter implements ObjectFactory {
95
+
96
+ private final io .cucumber .core .backend .ObjectFactory delegate ;
97
+
98
+ public ObjectFactoryAdapter (final io .cucumber .core .backend .ObjectFactory delegate ) {
99
+ this .delegate = Objects .requireNonNull (delegate );
100
+ }
101
+
102
+ @ Override
103
+ public void start () {
104
+ delegate .start ();
105
+ }
106
+
107
+ @ Override
108
+ public void stop () {
109
+ delegate .stop ();
110
+ }
111
+
112
+ @ Override
113
+ public boolean addClass (Class <?> arg0 ) {
114
+ return delegate .addClass (arg0 );
115
+ }
116
+
117
+ @ Override
118
+ public <T > T getInstance (Class <T > arg0 ) {
119
+ return delegate .getInstance (arg0 );
120
+ }
121
+
122
+ }
123
+
65
124
}
0 commit comments