Skip to content

Commit 4b261e6

Browse files
committed
[Core] Pass class loader to ServiceLoader.load invocations
Fixes: #2217, #2219
1 parent 31c1361 commit 4b261e6

File tree

11 files changed

+37
-20
lines changed

11 files changed

+37
-20
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1616
### Removed
1717

1818
### Fixed
19+
* [Core] Pass class loader to ServiceLoader.load invocations ([#2220](https://github.com/cucumber/cucumber-jvm/issues/2220) M.P. Korstanje)
1920

2021
## [6.9.1] (2020-12-14)
2122

Diff for: core/src/main/java/io/cucumber/core/runtime/BackendServiceLoader.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public BackendServiceLoader(
2929

3030
@Override
3131
public Collection<? extends Backend> get() {
32-
return get(ServiceLoader.load(BackendProviderService.class));
32+
ClassLoader classLoader = classLoaderSupplier.get();
33+
return get(ServiceLoader.load(BackendProviderService.class, classLoader));
3334
}
3435

3536
Collection<? extends Backend> get(Iterable<BackendProviderService> serviceLoader) {

Diff for: core/src/main/java/io/cucumber/core/runtime/ObjectFactoryServiceLoader.java

+13-4
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,25 @@
99
import java.util.Iterator;
1010
import java.util.Map;
1111
import java.util.ServiceLoader;
12+
import java.util.function.Supplier;
1213
import java.util.stream.Collectors;
1314
import java.util.stream.Stream;
1415

16+
import static java.lang.Thread.currentThread;
1517
import static java.util.Objects.requireNonNull;
1618

1719
public final class ObjectFactoryServiceLoader {
1820

21+
private final Supplier<ClassLoader> classLoaderSupplier;
1922
private final Options options;
2023

24+
@Deprecated
2125
public ObjectFactoryServiceLoader(Options options) {
26+
this(currentThread()::getContextClassLoader, options);
27+
}
28+
29+
public ObjectFactoryServiceLoader(Supplier<ClassLoader> classLoaderSupplier, Options options) {
30+
this.classLoaderSupplier = requireNonNull(classLoaderSupplier);
2231
this.options = requireNonNull(options);
2332
}
2433

@@ -38,9 +47,9 @@ public ObjectFactoryServiceLoader(Options options) {
3847
* @return an instance of {@link ObjectFactory}
3948
*/
4049
ObjectFactory loadObjectFactory() {
41-
Class<? extends ObjectFactory> objectFactoryClass = this.options.getObjectFactoryClass();
42-
43-
final ServiceLoader<ObjectFactory> loader = ServiceLoader.load(ObjectFactory.class);
50+
Class<? extends ObjectFactory> objectFactoryClass = options.getObjectFactoryClass();
51+
ClassLoader classLoader = classLoaderSupplier.get();
52+
ServiceLoader<ObjectFactory> loader = ServiceLoader.load(ObjectFactory.class, classLoader);
4453
if (objectFactoryClass == null) {
4554
return loadSingleObjectFactoryOrDefault(loader);
4655

@@ -50,7 +59,7 @@ ObjectFactory loadObjectFactory() {
5059
}
5160

5261
private static ObjectFactory loadSingleObjectFactoryOrDefault(ServiceLoader<ObjectFactory> loader) {
53-
final Iterator<ObjectFactory> objectFactories = loader.iterator();
62+
Iterator<ObjectFactory> objectFactories = loader.iterator();
5463

5564
ObjectFactory objectFactory;
5665
if (objectFactories.hasNext()) {

Diff for: core/src/main/java/io/cucumber/core/runtime/Runtime.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public Builder withEventBus(final EventBus eventBus) {
157157
}
158158

159159
public Runtime build() {
160-
final ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(
160+
final ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoader,
161161
runtimeOptions);
162162

163163
final ObjectFactorySupplier objectFactorySupplier = runtimeOptions.isMultiThreaded()

Diff for: core/src/test/java/io/cucumber/core/runtime/BackendServiceLoaderTest.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import org.junit.jupiter.api.Test;
66
import org.junit.jupiter.api.function.Executable;
77

8+
import java.util.function.Supplier;
9+
810
import static java.util.Collections.emptyList;
911
import static org.hamcrest.CoreMatchers.notNullValue;
1012
import static org.hamcrest.MatcherAssert.assertThat;
@@ -14,21 +16,21 @@
1416

1517
class BackendServiceLoaderTest {
1618

19+
final RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
20+
final Supplier<ClassLoader> classLoaderSupplier = this.getClass()::getClassLoader;
21+
final ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoaderSupplier,
22+
runtimeOptions);
23+
final ObjectFactorySupplier objectFactory = new SingletonObjectFactorySupplier(objectFactoryServiceLoader);
24+
1725
@Test
1826
void should_create_a_backend() {
19-
RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
20-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(runtimeOptions);
21-
ObjectFactorySupplier objectFactory = new SingletonObjectFactorySupplier(objectFactoryServiceLoader);
22-
BackendSupplier backendSupplier = new BackendServiceLoader(getClass()::getClassLoader, objectFactory);
27+
BackendSupplier backendSupplier = new BackendServiceLoader(classLoaderSupplier, objectFactory);
2328
assertThat(backendSupplier.get().iterator().next(), is(notNullValue()));
2429
}
2530

2631
@Test
2732
void should_throw_an_exception_when_no_backend_could_be_found() {
28-
RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
29-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(runtimeOptions);
30-
ObjectFactorySupplier objectFactory = new SingletonObjectFactorySupplier(objectFactoryServiceLoader);
31-
BackendServiceLoader backendSupplier = new BackendServiceLoader(getClass()::getClassLoader, objectFactory);
33+
BackendServiceLoader backendSupplier = new BackendServiceLoader(classLoaderSupplier, objectFactory);
3234

3335
Executable testMethod = () -> backendSupplier.get(emptyList()).iterator().next();
3436
CucumberException actualThrown = assertThrows(CucumberException.class, testMethod);

Diff for: core/src/test/java/io/cucumber/core/runtime/SingletonRunnerSupplierTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ class SingletonRunnerSupplierTest {
2222
void before() {
2323
Supplier<ClassLoader> classLoader = SingletonRunnerSupplier.class::getClassLoader;
2424
RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
25-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(runtimeOptions);
25+
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoader,
26+
runtimeOptions);
2627
ObjectFactorySupplier objectFactory = new SingletonObjectFactorySupplier(objectFactoryServiceLoader);
2728
BackendServiceLoader backendSupplier = new BackendServiceLoader(getClass()::getClassLoader, objectFactory);
2829
EventBus eventBus = new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID);

Diff for: core/src/test/java/io/cucumber/core/runtime/ThreadLocalRunnerSupplierTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class ThreadLocalRunnerSupplierTest {
3131
void before() {
3232
Supplier<ClassLoader> classLoader = ThreadLocalRunnerSupplierTest.class::getClassLoader;
3333
RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
34-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(runtimeOptions);
34+
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoader,
35+
runtimeOptions);
3536
ObjectFactorySupplier objectFactory = new SingletonObjectFactorySupplier(objectFactoryServiceLoader);
3637
BackendServiceLoader backendSupplier = new BackendServiceLoader(classLoader, objectFactory);
3738
eventBus = new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID);

Diff for: junit-platform-engine/src/main/java/io/cucumber/junit/platform/engine/CucumberEngineExecutionContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public final class CucumberEngineExecutionContext implements EngineExecutionCont
4444
Supplier<ClassLoader> classLoader = CucumberEngineExecutionContext.class::getClassLoader;
4545
log.debug(() -> "Parsing options");
4646
options = new CucumberEngineOptions(configurationParameters);
47-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(options);
47+
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoader, options);
4848
EventBus bus = synchronize(new TimeServiceEventBus(Clock.systemUTC(), UUID::randomUUID));
4949
TypeRegistryConfigurerSupplier typeRegistryConfigurerSupplier = new ScanningTypeRegistryConfigurerSupplier(
5050
classLoader, options);

Diff for: junit/src/main/java/io/cucumber/junit/Cucumber.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ public Cucumber(Class<?> clazz) throws InitializationError {
163163
ExitStatus exitStatus = new ExitStatus(runtimeOptions);
164164
this.plugins.addPlugin(exitStatus);
165165

166-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(runtimeOptions);
166+
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoader,
167+
runtimeOptions);
167168
ObjectFactorySupplier objectFactorySupplier = new ThreadLocalObjectFactorySupplier(objectFactoryServiceLoader);
168169
BackendSupplier backendSupplier = new BackendServiceLoader(clazz::getClassLoader, objectFactorySupplier);
169170
TypeRegistryConfigurerSupplier typeRegistryConfigurerSupplier = new ScanningTypeRegistryConfigurerSupplier(

Diff for: junit/src/test/java/io/cucumber/junit/FeatureRunnerTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ void should_not_create_step_descriptions_by_default() {
9494

9595
private FeatureRunner createFeatureRunner(Feature feature, JUnitOptions junitOption) {
9696
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(
97-
RuntimeOptions.defaultOptions());
97+
getClass()::getClassLoader, RuntimeOptions.defaultOptions());
9898
ObjectFactorySupplier objectFactory = new SingletonObjectFactorySupplier(objectFactoryServiceLoader);
9999
final RuntimeOptions runtimeOptions = RuntimeOptions.defaultOptions();
100100

Diff for: testng/src/main/java/io/cucumber/testng/TestNGCucumberRunner.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ public TestNGCucumberRunner(Class<?> clazz) {
9292
Plugins plugins = new Plugins(new PluginFactory(), runtimeOptions);
9393
ExitStatus exitStatus = new ExitStatus(runtimeOptions);
9494
plugins.addPlugin(exitStatus);
95-
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(runtimeOptions);
95+
ObjectFactoryServiceLoader objectFactoryServiceLoader = new ObjectFactoryServiceLoader(classLoader,
96+
runtimeOptions);
9697
ObjectFactorySupplier objectFactorySupplier = new ThreadLocalObjectFactorySupplier(objectFactoryServiceLoader);
9798
BackendServiceLoader backendSupplier = new BackendServiceLoader(clazz::getClassLoader, objectFactorySupplier);
9899
this.filters = new Filters(runtimeOptions);

0 commit comments

Comments
 (0)