Skip to content

Commit 709c593

Browse files
committed
Fix-ups due to #2230 review
1 parent a31881a commit 709c593

File tree

5 files changed

+77
-76
lines changed

5 files changed

+77
-76
lines changed

log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfig.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,9 @@ protected AsyncLoggerConfig(
108108
@Override
109109
public void initialize() {
110110
final Configuration configuration = getConfiguration();
111-
DisruptorConfiguration disruptorConfig = configuration.getExtension(DisruptorConfiguration.class);
112-
if (disruptorConfig == null) {
113-
disruptorConfig = DisruptorConfiguration.newBuilder().build();
114-
configuration.addExtension(disruptorConfig);
115-
}
111+
final DisruptorConfiguration disruptorConfig = configuration.addExtensionIfAbsent(
112+
DisruptorConfiguration.class,
113+
() -> DisruptorConfiguration.newBuilder().build());
116114
delegate = disruptorConfig.getAsyncLoggerConfigDelegate();
117115
delegate.setLogEventFactory(getLogEventFactory());
118116
super.initialize();

log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorConfiguration.java

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
2828
import org.apache.logging.log4j.plugins.PluginFactory;
2929
import org.apache.logging.log4j.status.StatusLogger;
30+
import org.apache.logging.log4j.util.Lazy;
3031
import org.apache.logging.log4j.util.LoaderUtil;
3132

3233
@Configurable(printObject = true)
@@ -37,7 +38,8 @@ public final class DisruptorConfiguration extends AbstractLifeCycle implements C
3738
private static final Logger LOGGER = StatusLogger.getLogger();
3839

3940
private final AsyncWaitStrategyFactory waitStrategyFactory;
40-
private AsyncLoggerConfigDisruptor loggerConfigDisruptor;
41+
private final Lazy<AsyncLoggerConfigDisruptor> loggerConfigDisruptor =
42+
Lazy.lazy(() -> new AsyncLoggerConfigDisruptor(getWaitStrategyFactory()));
4143

4244
private DisruptorConfiguration(final AsyncWaitStrategyFactory waitStrategyFactory) {
4345
this.waitStrategyFactory = waitStrategyFactory;
@@ -48,26 +50,23 @@ public AsyncWaitStrategyFactory getWaitStrategyFactory() {
4850
}
4951

5052
public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() {
51-
if (loggerConfigDisruptor == null) {
52-
loggerConfigDisruptor = new AsyncLoggerConfigDisruptor(waitStrategyFactory);
53-
}
54-
return loggerConfigDisruptor;
53+
return loggerConfigDisruptor.get();
5554
}
5655

5756
@Override
5857
public void start() {
59-
if (loggerConfigDisruptor != null) {
58+
if (loggerConfigDisruptor.isInitialized()) {
6059
LOGGER.info("Starting AsyncLoggerConfigDisruptor.");
61-
loggerConfigDisruptor.start();
60+
loggerConfigDisruptor.get().start();
6261
}
6362
super.start();
6463
}
6564

6665
@Override
67-
public boolean stop(long timeout, TimeUnit timeUnit) {
68-
if (loggerConfigDisruptor != null) {
66+
public boolean stop(final long timeout, final TimeUnit timeUnit) {
67+
if (loggerConfigDisruptor.isInitialized()) {
6968
LOGGER.info("Stopping AsyncLoggerConfigDisruptor.");
70-
loggerConfigDisruptor.stop(timeout, timeUnit);
69+
loggerConfigDisruptor.get().stop(timeout, timeUnit);
7170
}
7271
return super.stop(timeout, timeUnit);
7372
}
@@ -97,36 +96,31 @@ public Builder setWaitFactory(final String waitFactory) {
9796

9897
@Override
9998
public DisruptorConfiguration build() {
100-
final String effectiveClassName = Objects.toString(waitFactory, factoryClassName);
101-
final AsyncWaitStrategyFactory effectiveFactory;
102-
if (effectiveClassName != null) {
103-
effectiveFactory = createWaitStrategyFactory(effectiveClassName);
104-
} else {
105-
effectiveFactory = null;
106-
}
107-
if (effectiveFactory != null) {
108-
LOGGER.info("Using configured AsyncWaitStrategy factory {}.", effectiveClassName);
109-
} else {
110-
LOGGER.info("Using default AsyncWaitStrategy factory.");
111-
}
112-
return new DisruptorConfiguration(effectiveFactory);
99+
return new DisruptorConfiguration(
100+
createWaitStrategyFactory(Objects.toString(waitFactory, factoryClassName)));
113101
}
114102

115103
private static AsyncWaitStrategyFactory createWaitStrategyFactory(final String factoryClassName) {
116-
try {
117-
return LoaderUtil.newCheckedInstanceOf(factoryClassName, AsyncWaitStrategyFactory.class);
118-
} catch (final ClassCastException e) {
119-
LOGGER.error(
120-
"Ignoring factory '{}': it is not assignable to AsyncWaitStrategyFactory", factoryClassName);
121-
return null;
122-
} catch (ReflectiveOperationException | LinkageError e) {
123-
LOGGER.warn(
124-
"Invalid implementation class name value: error creating AsyncWaitStrategyFactory {}: {}",
125-
factoryClassName,
126-
e.getMessage(),
127-
e);
128-
return null;
104+
if (factoryClassName != null) {
105+
try {
106+
final AsyncWaitStrategyFactory asyncWaitStrategyFactory =
107+
LoaderUtil.newCheckedInstanceOf(factoryClassName, AsyncWaitStrategyFactory.class);
108+
LOGGER.info("Using configured AsyncWaitStrategy factory {}.", factoryClassName);
109+
return asyncWaitStrategyFactory;
110+
} catch (final ClassCastException e) {
111+
LOGGER.error(
112+
"Ignoring factory '{}': it is not assignable to AsyncWaitStrategyFactory",
113+
factoryClassName);
114+
} catch (final ReflectiveOperationException | LinkageError e) {
115+
LOGGER.warn(
116+
"Invalid implementation class name value: error creating AsyncWaitStrategyFactory {}: {}",
117+
factoryClassName,
118+
e.getMessage(),
119+
e);
120+
}
129121
}
122+
LOGGER.info("Using default AsyncWaitStrategy factory.");
123+
return null;
130124
}
131125
}
132126
}

log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import aQute.bnd.annotation.spi.ServiceConsumer;
2222
import java.lang.ref.WeakReference;
2323
import java.util.ArrayList;
24-
import java.util.Arrays;
2524
import java.util.Collections;
2625
import java.util.HashSet;
2726
import java.util.List;
@@ -91,7 +90,8 @@
9190
@ServiceConsumer(value = ScriptManagerFactory.class, cardinality = Cardinality.SINGLE, resolution = Resolution.OPTIONAL)
9291
public abstract class AbstractConfiguration extends AbstractFilterable implements Configuration {
9392

94-
private static final ConfigurationExtension[] EMPTY_EXTENSIONS = new ConfigurationExtension[0];
93+
private static final List<String> EXPECTED_ELEMENTS =
94+
List.of("\"Appenders\"", "\"Loggers\"", "\"Properties\"", "\"Scripts\"", "\"CustomLevels\"");
9595

9696
/**
9797
* The instance factory for this configuration. This may be a child factory to a LoggerContext
@@ -159,7 +159,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
159159
private final WeakReference<LoggerContext> loggerContext;
160160
private final PropertyEnvironment contextProperties;
161161
private final Lock configLock = new ReentrantLock();
162-
private ConfigurationExtension[] extensions = EMPTY_EXTENSIONS;
162+
private final List<ConfigurationExtension> extensions = new CopyOnWriteArrayList<>();
163163

164164
/**
165165
* Constructor.
@@ -659,7 +659,7 @@ protected void doConfigure() {
659659
if (!hasProperties) {
660660
final Map<String, String> map = this.getComponent(CONTEXT_PROPERTIES);
661661
final StrLookup lookup = map == null ? null : new PropertiesLookup(map);
662-
Interpolator interpolator = interpolatorFactory.newInterpolator(lookup);
662+
final Interpolator interpolator = interpolatorFactory.newInterpolator(lookup);
663663
instanceFactory.injectMembers(interpolator);
664664
runtimeStrSubstitutor.setVariableResolver(interpolator);
665665
configurationStrSubstitutor.setVariableResolver(interpolator);
@@ -676,6 +676,10 @@ protected void doConfigure() {
676676
}
677677
createConfiguration(child, null);
678678
if (child.getObject() == null) {
679+
LOGGER.warn(
680+
"Configuration element \"{}\" is ignored: try nesting it inside one of: {}.",
681+
child.getName(),
682+
EXPECTED_ELEMENTS);
679683
continue;
680684
}
681685
if ("Scripts".equalsIgnoreCase(child.getName())) {
@@ -686,40 +690,28 @@ protected void doConfigure() {
686690
appenders = child.getObject();
687691
} else if (child.isInstanceOf(Filter.class)) {
688692
addFilter(child.getObject(Filter.class));
689-
} else if ("Loggers".equalsIgnoreCase(child.getName())) {
690-
final Loggers l = child.getObject();
693+
} else if (child.isInstanceOf(Loggers.class)) {
694+
final Loggers l = child.getObject(Loggers.class);
691695
loggerConfigs = l.getMap();
692696
setLoggers = true;
693697
if (l.getRoot() != null) {
694698
root = l.getRoot();
695699
setRoot = true;
696700
}
697-
} else if ("CustomLevels".equalsIgnoreCase(child.getName())) {
698-
final CustomLevels levels = child.getObject(CustomLevels.class);
699-
if (levels == null) {
700-
LOGGER.error("Unable to load CustomLevels plugin");
701-
} else {
702-
customLevels = levels.getCustomLevels();
703-
}
701+
} else if (child.isInstanceOf(CustomLevels.class)) {
702+
customLevels = child.getObject(CustomLevels.class).getCustomLevels();
704703
} else if (child.isInstanceOf(CustomLevelConfig.class)) {
705704
final List<CustomLevelConfig> copy = new ArrayList<>(customLevels);
706705
copy.add(child.getObject(CustomLevelConfig.class));
707706
customLevels = copy;
708707
} else if (child.isInstanceOf(ConfigurationExtension.class)) {
709-
final ConfigurationExtension extension = child.getObject(ConfigurationExtension.class);
710-
if (extension == null) {
711-
LOGGER.error("Unable to load configuration extension {}.", child.getName());
712-
} else {
713-
addExtension(child.getObject());
714-
}
708+
addExtension(child.getObject(ConfigurationExtension.class));
715709
} else {
716-
final List<String> expected = Arrays.asList(
717-
"\"Appenders\"", "\"Loggers\"", "\"Properties\"", "\"Scripts\"", "\"CustomLevels\"");
718710
LOGGER.error(
719711
"Unknown object \"{}\" of type {} is ignored: try nesting it inside one of: {}.",
720712
child.getName(),
721713
child.getObject().getClass().getName(),
722-
expected);
714+
EXPECTED_ELEMENTS);
723715
}
724716
}
725717

@@ -1154,19 +1146,28 @@ public void setNanoClock(final NanoClock nanoClock) {
11541146
}
11551147

11561148
@Override
1157-
public void addExtension(ConfigurationExtension extension) {
1158-
Objects.requireNonNull(extension);
1159-
extensions = Arrays.copyOf(extensions, extensions.length + 1);
1160-
extensions[extensions.length - 1] = extension;
1149+
public <T extends ConfigurationExtension> T addExtensionIfAbsent(
1150+
final Class<T> extensionType, final Supplier<? extends T> supplier) {
1151+
for (final ConfigurationExtension extension : extensions) {
1152+
if (extensionType.isInstance(extension)) {
1153+
return extensionType.cast(extension);
1154+
}
1155+
}
1156+
return addExtension(supplier.get());
1157+
}
1158+
1159+
private <T extends ConfigurationExtension> T addExtension(final T extension) {
1160+
extensions.add(Objects.requireNonNull(extension));
1161+
return extension;
11611162
}
11621163

11631164
@Override
1164-
public <T extends ConfigurationExtension> T getExtension(Class<T> extensionType) {
1165+
public <T extends ConfigurationExtension> T getExtension(final Class<T> extensionType) {
11651166
T result = null;
11661167
for (final ConfigurationExtension extension : extensions) {
11671168
if (extensionType.isInstance(extension)) {
11681169
if (result == null) {
1169-
result = (T) extension;
1170+
result = extensionType.cast(extension);
11701171
} else {
11711172
LOGGER.warn(
11721173
"Multiple configuration elements found for type {}. Only the first will be used.",

log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,17 +238,25 @@ default RecyclerFactory getRecyclerFactory() {
238238
}
239239

240240
/**
241-
* Registers a new configuration extension.
242-
*
243-
* @param extension a configuration extension.
241+
* Registers a new configuration extension, if it doesn't exist.
242+
* <p>
243+
* To preventing polluting the main configuration element,
244+
* each JAR that wishes to extend the {@link Configuration} should use a single child element.
245+
* </p>
246+
* @param extensionType the concrete type of the extension,
247+
* @param supplier a factory to create a new extension element,
248+
* @return the current extension if present or a newly generated one.
244249
* @since 3.0
250+
* @see #getExtension(Class)
245251
*/
246-
void addExtension(ConfigurationExtension extension);
252+
<T extends ConfigurationExtension> T addExtensionIfAbsent(Class<T> extensionType, Supplier<? extends T> supplier);
247253

248254
/**
249255
* Returns an extension of the given type.
250-
*
251-
* @param extensionType a type of extension,
256+
* <p>
257+
* Only the first extension of the given type is returned.
258+
* </p>
259+
* @param extensionType a concrete type of the extension,
252260
* @return an extension the matches the given type.
253261
* @since 3.0
254262
*/

log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationExtension.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
package org.apache.logging.log4j.core.config;
1818

1919
/**
20-
* A {@link ConfigurationExtension} is used to add new child elements to a {@link Configuration}.
20+
* Marker interface used by new child elements of a {@link Configuration}.
2121
*/
2222
public interface ConfigurationExtension {}

0 commit comments

Comments
 (0)