Skip to content

Commit 2c52f5f

Browse files
committed
fix: Explicit provider fails when used with module system
this fixes #392 Signed-off-by: Robert Scholte <[email protected]>
1 parent 8c4ea8f commit 2c52f5f

File tree

2 files changed

+41
-32
lines changed

2 files changed

+41
-32
lines changed

slf4j-api/src/main/java/org/slf4j/LoggerFactory.java

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@
3333
import java.util.ArrayList;
3434
import java.util.Arrays;
3535
import java.util.Enumeration;
36-
import java.util.Iterator;
3736
import java.util.LinkedHashSet;
3837
import java.util.List;
38+
import java.util.Objects;
3939
import java.util.ServiceConfigurationError;
4040
import java.util.ServiceLoader;
41+
import java.util.ServiceLoader.Provider;
4142
import java.util.Set;
4243
import java.util.concurrent.LinkedBlockingQueue;
44+
import java.util.stream.Collectors;
45+
import java.util.stream.Stream;
4346

4447
import org.slf4j.event.SubstituteLoggingEvent;
4548
import org.slf4j.helpers.NOP_FallbackServiceProvider;
@@ -110,24 +113,32 @@ public final class LoggerFactory {
110113

111114
// Package access for tests
112115
static List<SLF4JServiceProvider> findServiceProviders() {
113-
List<SLF4JServiceProvider> providerList = new ArrayList<>();
114116

115117
// retain behaviour similar to that of 1.7 series and earlier. More specifically, use the class loader that
116118
// loaded the present class to search for services
117119
final ClassLoader classLoaderOfLoggerFactory = LoggerFactory.class.getClassLoader();
118120

119-
SLF4JServiceProvider explicitProvider = loadExplicitlySpecified(classLoaderOfLoggerFactory);
120-
if(explicitProvider != null) {
121-
providerList.add(explicitProvider);
122-
return providerList;
123-
}
124-
121+
122+
ServiceLoader<SLF4JServiceProvider> serviceLoader = getServiceLoader(classLoaderOfLoggerFactory);
125123

126-
ServiceLoader<SLF4JServiceProvider> serviceLoader = getServiceLoader(classLoaderOfLoggerFactory);
124+
Stream<Provider<SLF4JServiceProvider>> stream = serviceLoader.stream();
127125

128-
Iterator<SLF4JServiceProvider> iterator = serviceLoader.iterator();
129-
while (iterator.hasNext()) {
130-
safelyInstantiate(providerList, iterator);
126+
String explicitlySpecified = System.getProperty(PROVIDER_PROPERTY_KEY, "");
127+
128+
if (!explicitlySpecified.isEmpty()) {
129+
stream = stream.filter(s -> s.type().getName().equals(explicitlySpecified));
130+
}
131+
132+
List<SLF4JServiceProvider> providerList = stream.map(LoggerFactory::safelyInstantiate)
133+
.filter(Objects::nonNull)
134+
.collect(Collectors.toList());
135+
136+
if(providerList.isEmpty() && !explicitlySpecified.isEmpty())
137+
{
138+
SLF4JServiceProvider explicitProvider = loadExplicitlySpecified(explicitlySpecified, classLoaderOfLoggerFactory);
139+
if(explicitProvider != null) {
140+
return Arrays.asList(explicitProvider);
141+
}
131142
}
132143
return providerList;
133144
}
@@ -144,13 +155,18 @@ private static ServiceLoader<SLF4JServiceProvider> getServiceLoader(final ClassL
144155
return serviceLoader;
145156
}
146157

147-
private static void safelyInstantiate(List<SLF4JServiceProvider> providerList, Iterator<SLF4JServiceProvider> iterator) {
158+
/**
159+
*
160+
* @param provider
161+
* @return the initiated provider or {@code null} if it fails
162+
*/
163+
private static SLF4JServiceProvider safelyInstantiate(Provider<SLF4JServiceProvider> provider) {
148164
try {
149-
SLF4JServiceProvider provider = iterator.next();
150-
providerList.add(provider);
165+
return provider.get();
151166
} catch (ServiceConfigurationError e) {
152167
Reporter.error("A service provider failed to instantiate:\n" + e.getMessage());
153168
}
169+
return null;
154170
}
155171

156172
/**
@@ -212,11 +228,13 @@ private final static void bind() {
212228
}
213229
}
214230

215-
static SLF4JServiceProvider loadExplicitlySpecified(ClassLoader classLoader) {
216-
String explicitlySpecified = System.getProperty(PROVIDER_PROPERTY_KEY);
217-
if (null == explicitlySpecified || explicitlySpecified.isEmpty()) {
218-
return null;
219-
}
231+
/**
232+
*
233+
* @param explicitlySpecified the classname of the provider, never {@code null}
234+
* @param classLoader the classloader, never {@code null}
235+
* @return
236+
*/
237+
static SLF4JServiceProvider loadExplicitlySpecified(String explicitlySpecified, ClassLoader classLoader) {
220238
try {
221239
String message = String.format("Attempting to load provider \"%s\" specified via \"%s\" system property", explicitlySpecified, PROVIDER_PROPERTY_KEY);
222240
Reporter.info(message);

slf4j-api/src/test/java/org/slf4j/LoggerFactoryTest.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import java.io.ByteArrayOutputStream;
1010
import java.io.PrintStream;
1111

12-
import static org.hamcrest.CoreMatchers.is;
1312
import static org.junit.Assert.*;
1413

1514
public class LoggerFactoryTest {
@@ -33,32 +32,24 @@ public void cleanUp() {
3332

3433
@Test
3534
public void testExplicitlySpecified() {
36-
System.setProperty(LoggerFactory.PROVIDER_PROPERTY_KEY, "org.slf4j.LoggerFactoryTest$TestingProvider");
37-
SLF4JServiceProvider provider = LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory);
35+
SLF4JServiceProvider provider = LoggerFactory.loadExplicitlySpecified("org.slf4j.LoggerFactoryTest$TestingProvider", classLoaderOfLoggerFactory);
3836
assertTrue("provider should be instance of TestingProvider class", provider instanceof TestingProvider);
3937
assertTrue(mockedSyserr.toString().contains(" Attempting to load provider \"org.slf4j.LoggerFactoryTest$TestingProvider\" specified via \"slf4j.provider\" system property"));
4038
System.out.println(mockedSyserr.toString());
4139

4240

4341
}
4442

45-
@Test
46-
public void testExplicitlySpecifiedNull() {
47-
assertNull(LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory));
48-
}
49-
5043
@Test
5144
public void testExplicitlySpecifyMissingServiceProvider() {
52-
System.setProperty(LoggerFactory.PROVIDER_PROPERTY_KEY, "com.example.ServiceProvider");
53-
SLF4JServiceProvider provider = LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory);
45+
SLF4JServiceProvider provider = LoggerFactory.loadExplicitlySpecified("com.example.ServiceProvider", classLoaderOfLoggerFactory);
5446
assertNull(provider);
5547
assertTrue(mockedSyserr.toString().contains("Failed to instantiate the specified SLF4JServiceProvider (com.example.ServiceProvider)"));
5648
}
5749

5850
@Test
5951
public void testExplicitlySpecifyNonServiceProvider() {
60-
System.setProperty(LoggerFactory.PROVIDER_PROPERTY_KEY, "java.lang.String");
61-
assertNull(LoggerFactory.loadExplicitlySpecified(classLoaderOfLoggerFactory));
52+
assertNull(LoggerFactory.loadExplicitlySpecified("java.lang.String", classLoaderOfLoggerFactory));
6253
assertTrue(mockedSyserr.toString().contains("Specified SLF4JServiceProvider (java.lang.String) does not implement SLF4JServiceProvider interface"));
6354
}
6455

0 commit comments

Comments
 (0)