1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.config;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.Serializable;
23 import java.lang.ref.WeakReference;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Objects;
33 import java.util.Set;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.ConcurrentMap;
36 import java.util.concurrent.CopyOnWriteArrayList;
37 import java.util.concurrent.TimeUnit;
38
39 import org.apache.logging.log4j.Level;
40 import org.apache.logging.log4j.core.Appender;
41 import org.apache.logging.log4j.core.Filter;
42 import org.apache.logging.log4j.core.Layout;
43 import org.apache.logging.log4j.core.LifeCycle2;
44 import org.apache.logging.log4j.core.LogEvent;
45 import org.apache.logging.log4j.core.LoggerContext;
46 import org.apache.logging.log4j.core.Version;
47 import org.apache.logging.log4j.core.appender.AsyncAppender;
48 import org.apache.logging.log4j.core.appender.ConsoleAppender;
49 import org.apache.logging.log4j.core.async.AsyncLoggerConfig;
50 import org.apache.logging.log4j.core.async.AsyncLoggerConfigDelegate;
51 import org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor;
52 import org.apache.logging.log4j.core.config.plugins.util.PluginBuilder;
53 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
54 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
55 import org.apache.logging.log4j.core.filter.AbstractFilterable;
56 import org.apache.logging.log4j.core.layout.PatternLayout;
57 import org.apache.logging.log4j.core.lookup.Interpolator;
58 import org.apache.logging.log4j.core.lookup.MapLookup;
59 import org.apache.logging.log4j.core.lookup.StrLookup;
60 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
61 import org.apache.logging.log4j.core.net.Advertiser;
62 import org.apache.logging.log4j.core.script.AbstractScript;
63 import org.apache.logging.log4j.core.script.ScriptManager;
64 import org.apache.logging.log4j.core.script.ScriptRef;
65 import org.apache.logging.log4j.core.util.Constants;
66 import org.apache.logging.log4j.core.util.DummyNanoClock;
67 import org.apache.logging.log4j.core.util.Loader;
68 import org.apache.logging.log4j.core.util.NameUtil;
69 import org.apache.logging.log4j.core.util.NanoClock;
70 import org.apache.logging.log4j.core.util.WatchManager;
71 import org.apache.logging.log4j.util.PropertiesUtil;
72
73
74
75
76 public abstract class AbstractConfiguration extends AbstractFilterable implements Configuration {
77
78 private static final int BUF_SIZE = 16384;
79
80
81
82
83 protected Node rootNode;
84
85
86
87
88 protected final List<ConfigurationListener> listeners = new CopyOnWriteArrayList<>();
89
90
91
92
93 protected final List<String> pluginPackages = new ArrayList<>();
94
95
96
97
98 protected PluginManager pluginManager;
99
100
101
102
103 protected boolean isShutdownHookEnabled = true;
104
105
106
107
108 protected long shutdownTimeoutMillis = 0;
109
110
111
112
113 protected ScriptManager scriptManager;
114
115
116
117
118 private Advertiser advertiser = new DefaultAdvertiser();
119 private Node advertiserNode = null;
120 private Object advertisement;
121 private String name;
122 private ConcurrentMap<String, Appender> appenders = new ConcurrentHashMap<>();
123 private ConcurrentMap<String, LoggerConfig> loggerConfigs = new ConcurrentHashMap<>();
124 private List<CustomLevelConfig> customLevels = Collections.emptyList();
125 private final ConcurrentMap<String, String> properties = new ConcurrentHashMap<>();
126 private final StrLookup tempLookup = new Interpolator(properties);
127 private final StrSubstitutor subst = new StrSubstitutor(tempLookup);
128 private LoggerConfig root = new LoggerConfig();
129 private final ConcurrentMap<String, Object> componentMap = new ConcurrentHashMap<>();
130 private final ConfigurationSource configurationSource;
131 private final ConfigurationScheduler configurationScheduler = new ConfigurationScheduler();
132 private final WatchManager watchManager = new WatchManager(configurationScheduler);
133 private AsyncLoggerConfigDisruptor asyncLoggerConfigDisruptor;
134 private NanoClock nanoClock = new DummyNanoClock();
135 private final WeakReference<LoggerContext> loggerContext;
136
137
138
139
140 protected AbstractConfiguration(final LoggerContext loggerContext, final ConfigurationSource configurationSource) {
141 this.loggerContext = new WeakReference<>(loggerContext);
142
143
144 this.configurationSource = Objects.requireNonNull(configurationSource, "configurationSource is null");
145 componentMap.put(Configuration.CONTEXT_PROPERTIES, properties);
146 pluginManager = new PluginManager(Node.CATEGORY);
147 rootNode = new Node();
148 setState(State.INITIALIZING);
149
150 }
151
152 @Override
153 public ConfigurationSource getConfigurationSource() {
154 return configurationSource;
155 }
156
157 @Override
158 public List<String> getPluginPackages() {
159 return pluginPackages;
160 }
161
162 @Override
163 public Map<String, String> getProperties() {
164 return properties;
165 }
166
167 @Override
168 public ScriptManager getScriptManager() {
169 return scriptManager;
170 }
171
172 public void setScriptManager(final ScriptManager scriptManager) {
173 this.scriptManager = scriptManager;
174 }
175
176 public PluginManager getPluginManager() {
177 return pluginManager;
178 }
179
180 public void setPluginManager(final PluginManager pluginManager) {
181 this.pluginManager = pluginManager;
182 }
183
184 @Override
185 public WatchManager getWatchManager() {
186 return watchManager;
187 }
188
189 @Override
190 public ConfigurationScheduler getScheduler() {
191 return configurationScheduler;
192 }
193
194 public Node getRootNode() {
195 return rootNode;
196 }
197
198 @Override
199 public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() {
200
201
202 if (asyncLoggerConfigDisruptor == null) {
203 asyncLoggerConfigDisruptor = new AsyncLoggerConfigDisruptor();
204 }
205 return asyncLoggerConfigDisruptor;
206 }
207
208
209
210
211 @Override
212 public void initialize() {
213 LOGGER.debug(Version.getProductString() + " initializing configuration {}", this);
214 subst.setConfiguration(this);
215 try {
216 scriptManager = new ScriptManager(this, watchManager);
217 } catch (final LinkageError | Exception e) {
218
219 LOGGER.info("Cannot initialize scripting support because this JRE does not support it.", e);
220 }
221 pluginManager.collectPlugins(pluginPackages);
222 final PluginManager levelPlugins = new PluginManager(Level.CATEGORY);
223 levelPlugins.collectPlugins(pluginPackages);
224 final Map<String, PluginType<?>> plugins = levelPlugins.getPlugins();
225 if (plugins != null) {
226 for (final PluginType<?> type : plugins.values()) {
227 try {
228
229 Loader.initializeClass(type.getPluginClass().getName(), type.getPluginClass().getClassLoader());
230 } catch (final Exception e) {
231 LOGGER.error("Unable to initialize {} due to {}", type.getPluginClass().getName(), e.getClass()
232 .getSimpleName(), e);
233 }
234 }
235 }
236 setup();
237 setupAdvertisement();
238 doConfigure();
239 setState(State.INITIALIZED);
240 LOGGER.debug("Configuration {} initialized", this);
241 }
242
243
244
245
246 @Override
247 public void start() {
248
249 if (getState().equals(State.INITIALIZING)) {
250 initialize();
251 }
252 LOGGER.debug("Starting configuration {}", this);
253 this.setStarting();
254 if (watchManager.getIntervalSeconds() > 0) {
255 watchManager.start();
256 }
257 if (hasAsyncLoggers()) {
258 asyncLoggerConfigDisruptor.start();
259 }
260 final Set<LoggerConfig> alreadyStarted = new HashSet<>();
261 for (final LoggerConfig logger : loggerConfigs.values()) {
262 logger.start();
263 alreadyStarted.add(logger);
264 }
265 for (final Appender appender : appenders.values()) {
266 appender.start();
267 }
268 if (!alreadyStarted.contains(root)) {
269 root.start();
270 }
271 super.start();
272 LOGGER.debug("Started configuration {} OK.", this);
273 }
274
275 private boolean hasAsyncLoggers() {
276 if (root instanceof AsyncLoggerConfig) {
277 return true;
278 }
279 for (final LoggerConfig logger : loggerConfigs.values()) {
280 if (logger instanceof AsyncLoggerConfig) {
281 return true;
282 }
283 }
284 return false;
285 }
286
287
288
289
290 @Override
291 public boolean stop(final long timeout, final TimeUnit timeUnit) {
292 this.setStopping();
293 super.stop(timeout, timeUnit, false);
294 LOGGER.trace("Stopping {}...", this);
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 for (final LoggerConfig loggerConfig : loggerConfigs.values()) {
310 loggerConfig.getReliabilityStrategy().beforeStopConfiguration(this);
311 }
312 root.getReliabilityStrategy().beforeStopConfiguration(this);
313
314 final String cls = getClass().getSimpleName();
315 LOGGER.trace("{} notified {} ReliabilityStrategies that config will be stopped.", cls, loggerConfigs.size()
316 + 1);
317
318 if (!loggerConfigs.isEmpty()) {
319 LOGGER.trace("{} stopping {} LoggerConfigs.", cls, loggerConfigs.size());
320 for (final LoggerConfig logger : loggerConfigs.values()) {
321 logger.stop(timeout, timeUnit);
322 }
323 }
324 LOGGER.trace("{} stopping root LoggerConfig.", cls);
325 if (!root.isStopped()) {
326 root.stop(timeout, timeUnit);
327 }
328
329 if (hasAsyncLoggers()) {
330 LOGGER.trace("{} stopping AsyncLoggerConfigDisruptor.", cls);
331 asyncLoggerConfigDisruptor.stop(timeout, timeUnit);
332 }
333
334
335 final Appender[] array = appenders.values().toArray(new Appender[appenders.size()]);
336 final List<Appender> async = getAsyncAppenders(array);
337 if (!async.isEmpty()) {
338
339 LOGGER.trace("{} stopping {} AsyncAppenders.", cls, async.size());
340 for (final Appender appender : async) {
341 if (appender instanceof LifeCycle2) {
342 ((LifeCycle2) appender).stop(timeout, timeUnit);
343 } else {
344 appender.stop();
345 }
346 }
347 }
348
349 LOGGER.trace("{} notifying ReliabilityStrategies that appenders will be stopped.", cls);
350 for (final LoggerConfig loggerConfig : loggerConfigs.values()) {
351 loggerConfig.getReliabilityStrategy().beforeStopAppenders();
352 }
353 root.getReliabilityStrategy().beforeStopAppenders();
354
355 LOGGER.trace("{} stopping remaining Appenders.", cls);
356 int appenderCount = 0;
357 for (int i = array.length - 1; i >= 0; --i) {
358 if (array[i].isStarted()) {
359 if (array[i] instanceof LifeCycle2) {
360 ((LifeCycle2) array[i]).stop(timeout, timeUnit);
361 } else {
362 array[i].stop();
363 }
364 appenderCount++;
365 }
366 }
367 LOGGER.trace("{} stopped {} remaining Appenders.", cls, appenderCount);
368
369 LOGGER.trace("{} cleaning Appenders from {} LoggerConfigs.", cls, loggerConfigs.size() + 1);
370 for (final LoggerConfig loggerConfig : loggerConfigs.values()) {
371
372
373
374
375
376
377 loggerConfig.clearAppenders();
378 }
379 root.clearAppenders();
380
381 if (watchManager.isStarted()) {
382 watchManager.stop(timeout, timeUnit);
383 }
384 configurationScheduler.stop(timeout, timeUnit);
385
386 if (advertiser != null && advertisement != null) {
387 advertiser.unadvertise(advertisement);
388 }
389 setStopped();
390 LOGGER.debug("Stopped {} OK", this);
391 return true;
392 }
393
394 private List<Appender> getAsyncAppenders(final Appender[] all) {
395 final List<Appender> result = new ArrayList<>();
396 for (int i = all.length - 1; i >= 0; --i) {
397 if (all[i] instanceof AsyncAppender) {
398 result.add(all[i]);
399 }
400 }
401 return result;
402 }
403
404 @Override
405 public boolean isShutdownHookEnabled() {
406 return isShutdownHookEnabled;
407 }
408
409 @Override
410 public long getShutdownTimeoutMillis() {
411 return shutdownTimeoutMillis;
412 }
413
414 public void setup() {
415
416 }
417
418 protected Level getDefaultStatus() {
419 final String statusLevel = PropertiesUtil.getProperties().getStringProperty(
420 Constants.LOG4J_DEFAULT_STATUS_LEVEL, Level.ERROR.name());
421 try {
422 return Level.toLevel(statusLevel);
423 } catch (final Exception ex) {
424 return Level.ERROR;
425 }
426 }
427
428 protected void createAdvertiser(final String advertiserString, final ConfigurationSource configSource,
429 final byte[] buffer, final String contentType) {
430 if (advertiserString != null) {
431 final Node node = new Node(null, advertiserString, null);
432 final Map<String, String> attributes = node.getAttributes();
433 attributes.put("content", new String(buffer));
434 attributes.put("contentType", contentType);
435 attributes.put("name", "configuration");
436 if (configSource.getLocation() != null) {
437 attributes.put("location", configSource.getLocation());
438 }
439 advertiserNode = node;
440 }
441 }
442
443 private void setupAdvertisement() {
444 if (advertiserNode != null) {
445 final String nodeName = advertiserNode.getName();
446 final PluginType<?> type = pluginManager.getPluginType(nodeName);
447 if (type != null) {
448 final Class<? extends Advertiser> clazz = type.getPluginClass().asSubclass(Advertiser.class);
449 try {
450 advertiser = clazz.newInstance();
451 advertisement = advertiser.advertise(advertiserNode.getAttributes());
452 } catch (final InstantiationException e) {
453 LOGGER.error("InstantiationException attempting to instantiate advertiser: {}", nodeName, e);
454 } catch (final IllegalAccessException e) {
455 LOGGER.error("IllegalAccessException attempting to instantiate advertiser: {}", nodeName, e);
456 }
457 }
458 }
459 }
460
461 @SuppressWarnings("unchecked")
462 @Override
463 public <T> T getComponent(final String componentName) {
464 return (T) componentMap.get(componentName);
465 }
466
467 @Override
468 public void addComponent(final String componentName, final Object obj) {
469 componentMap.putIfAbsent(componentName, obj);
470 }
471
472 protected void preConfigure(final Node node) {
473 try {
474 for (final Node child : node.getChildren()) {
475 if (child.getType() == null) {
476 LOGGER.error("Unable to locate plugin type for " + child.getName());
477 continue;
478 }
479 final Class<?> clazz = child.getType().getPluginClass();
480 if (clazz.isAnnotationPresent(Scheduled.class)) {
481 configurationScheduler.incrementScheduledItems();
482 }
483 preConfigure(child);
484 }
485 } catch (final Exception ex) {
486 LOGGER.error("Error capturing node data for node " + node.getName(), ex);
487 }
488 }
489
490 protected void doConfigure() {
491 preConfigure(rootNode);
492 configurationScheduler.start();
493 if (rootNode.hasChildren() && rootNode.getChildren().get(0).getName().equalsIgnoreCase("Properties")) {
494 final Node first = rootNode.getChildren().get(0);
495 createConfiguration(first, null);
496 if (first.getObject() != null) {
497 subst.setVariableResolver((StrLookup) first.getObject());
498 }
499 } else {
500 final Map<String, String> map = this.getComponent(CONTEXT_PROPERTIES);
501 final StrLookup lookup = map == null ? null : new MapLookup(map);
502 subst.setVariableResolver(new Interpolator(lookup, pluginPackages));
503 }
504
505 boolean setLoggers = false;
506 boolean setRoot = false;
507 for (final Node child : rootNode.getChildren()) {
508 if (child.getName().equalsIgnoreCase("Properties")) {
509 if (tempLookup == subst.getVariableResolver()) {
510 LOGGER.error("Properties declaration must be the first element in the configuration");
511 }
512 continue;
513 }
514 createConfiguration(child, null);
515 if (child.getObject() == null) {
516 continue;
517 }
518 if (child.getName().equalsIgnoreCase("Scripts")) {
519 for (final AbstractScript script : child.getObject(AbstractScript[].class)) {
520 if (script instanceof ScriptRef) {
521 LOGGER.error("Script reference to {} not added. Scripts definition cannot contain script references",
522 script.getName());
523 } else {
524 if (scriptManager != null) {
525 scriptManager.addScript(script);
526 }}
527 }
528 } else if (child.getName().equalsIgnoreCase("Appenders")) {
529 appenders = child.getObject();
530 } else if (child.isInstanceOf(Filter.class)) {
531 addFilter(child.getObject(Filter.class));
532 } else if (child.getName().equalsIgnoreCase("Loggers")) {
533 final Loggers l = child.getObject();
534 loggerConfigs = l.getMap();
535 setLoggers = true;
536 if (l.getRoot() != null) {
537 root = l.getRoot();
538 setRoot = true;
539 }
540 } else if (child.getName().equalsIgnoreCase("CustomLevels")) {
541 customLevels = child.getObject(CustomLevels.class).getCustomLevels();
542 } else if (child.isInstanceOf(CustomLevelConfig.class)) {
543 final List<CustomLevelConfig> copy = new ArrayList<>(customLevels);
544 copy.add(child.getObject(CustomLevelConfig.class));
545 customLevels = copy;
546 } else {
547 final List<String> expected = Arrays.asList("\"Appenders\"", "\"Loggers\"", "\"Properties\"",
548 "\"Scripts\"", "\"CustomLevels\"");
549 LOGGER.error("Unknown object \"{}\" of type {} is ignored: try nesting it inside one of: {}.",
550 child.getName(), child.getObject().getClass().getName(), expected);
551 }
552 }
553
554 if (!setLoggers) {
555 LOGGER.warn("No Loggers were configured, using default. Is the Loggers element missing?");
556 setToDefault();
557 return;
558 } else if (!setRoot) {
559 LOGGER.warn("No Root logger was configured, creating default ERROR-level Root logger with Console appender");
560 setToDefault();
561
562 }
563
564 for (final Map.Entry<String, LoggerConfig> entry : loggerConfigs.entrySet()) {
565 final LoggerConfig loggerConfig = entry.getValue();
566 for (final AppenderRef ref : loggerConfig.getAppenderRefs()) {
567 final Appender app = appenders.get(ref.getRef());
568 if (app != null) {
569 loggerConfig.addAppender(app, ref.getLevel(), ref.getFilter());
570 } else {
571 LOGGER.error("Unable to locate appender \"{}\" for logger config \"{}\"", ref.getRef(),
572 loggerConfig);
573 }
574 }
575
576 }
577
578 setParents();
579 }
580
581 protected void setToDefault() {
582
583 setName(DefaultConfiguration.DEFAULT_NAME + "@" + Integer.toHexString(hashCode()));
584 final Layout<? extends Serializable> layout = PatternLayout.newBuilder()
585 .withPattern(DefaultConfiguration.DEFAULT_PATTERN)
586 .withConfiguration(this)
587 .build();
588 final Appender appender = ConsoleAppender.createDefaultAppenderForLayout(layout);
589 appender.start();
590 addAppender(appender);
591 final LoggerConfig rootLoggerConfig = getRootLogger();
592 rootLoggerConfig.addAppender(appender, null, null);
593
594 final Level defaultLevel = Level.ERROR;
595 final String levelName = PropertiesUtil.getProperties().getStringProperty(DefaultConfiguration.DEFAULT_LEVEL,
596 defaultLevel.name());
597 final Level level = Level.valueOf(levelName);
598 rootLoggerConfig.setLevel(level != null ? level : defaultLevel);
599 }
600
601
602
603
604
605
606 public void setName(final String name) {
607 this.name = name;
608 }
609
610
611
612
613
614
615 @Override
616 public String getName() {
617 return name;
618 }
619
620
621
622
623
624
625 @Override
626 public void addListener(final ConfigurationListener listener) {
627 listeners.add(listener);
628 }
629
630
631
632
633
634
635 @Override
636 public void removeListener(final ConfigurationListener listener) {
637 listeners.remove(listener);
638 }
639
640
641
642
643
644
645
646 @Override
647 @SuppressWarnings("unchecked")
648 public <T extends Appender> T getAppender(final String appenderName) {
649 return (T) appenders.get(appenderName);
650 }
651
652
653
654
655
656
657 @Override
658 public Map<String, Appender> getAppenders() {
659 return appenders;
660 }
661
662
663
664
665
666
667 @Override
668 public void addAppender(final Appender appender) {
669 appenders.putIfAbsent(appender.getName(), appender);
670 }
671
672 @Override
673 public StrSubstitutor getStrSubstitutor() {
674 return subst;
675 }
676
677 @Override
678 public void setAdvertiser(final Advertiser advertiser) {
679 this.advertiser = advertiser;
680 }
681
682 @Override
683 public Advertiser getAdvertiser() {
684 return advertiser;
685 }
686
687
688
689
690
691
692
693 @Override
694 public ReliabilityStrategy getReliabilityStrategy(final LoggerConfig loggerConfig) {
695 return ReliabilityStrategyFactory.getReliabilityStrategy(loggerConfig);
696 }
697
698
699
700
701
702
703
704
705
706
707 @Override
708 public synchronized void addLoggerAppender(final org.apache.logging.log4j.core.Logger logger,
709 final Appender appender) {
710 final String loggerName = logger.getName();
711 appenders.putIfAbsent(appender.getName(), appender);
712 final LoggerConfig lc = getLoggerConfig(loggerName);
713 if (lc.getName().equals(loggerName)) {
714 lc.addAppender(appender, null, null);
715 } else {
716 final LoggerConfig nlc = new LoggerConfig(loggerName, lc.getLevel(), lc.isAdditive());
717 nlc.addAppender(appender, null, null);
718 nlc.setParent(lc);
719 loggerConfigs.putIfAbsent(loggerName, nlc);
720 setParents();
721 logger.getContext().updateLoggers();
722 }
723 }
724
725
726
727
728
729
730
731
732
733
734 @Override
735 public synchronized void addLoggerFilter(final org.apache.logging.log4j.core.Logger logger, final Filter filter) {
736 final String loggerName = logger.getName();
737 final LoggerConfig lc = getLoggerConfig(loggerName);
738 if (lc.getName().equals(loggerName)) {
739 lc.addFilter(filter);
740 } else {
741 final LoggerConfig nlc = new LoggerConfig(loggerName, lc.getLevel(), lc.isAdditive());
742 nlc.addFilter(filter);
743 nlc.setParent(lc);
744 loggerConfigs.putIfAbsent(loggerName, nlc);
745 setParents();
746 logger.getContext().updateLoggers();
747 }
748 }
749
750
751
752
753
754
755
756
757
758
759 @Override
760 public synchronized void setLoggerAdditive(final org.apache.logging.log4j.core.Logger logger, final boolean additive) {
761 final String loggerName = logger.getName();
762 final LoggerConfig lc = getLoggerConfig(loggerName);
763 if (lc.getName().equals(loggerName)) {
764 lc.setAdditive(additive);
765 } else {
766 final LoggerConfig nlc = new LoggerConfig(loggerName, lc.getLevel(), additive);
767 nlc.setParent(lc);
768 loggerConfigs.putIfAbsent(loggerName, nlc);
769 setParents();
770 logger.getContext().updateLoggers();
771 }
772 }
773
774
775
776
777
778
779
780
781 public synchronized void removeAppender(final String appenderName) {
782 for (final LoggerConfig logger : loggerConfigs.values()) {
783 logger.removeAppender(appenderName);
784 }
785 final Appender app = appenders.remove(appenderName);
786
787 if (app != null) {
788 app.stop();
789 }
790 }
791
792
793
794
795
796
797 @Override
798 public List<CustomLevelConfig> getCustomLevels() {
799 return Collections.unmodifiableList(customLevels);
800 }
801
802
803
804
805
806
807
808
809 @Override
810 public LoggerConfig getLoggerConfig(final String loggerName) {
811 LoggerConfig loggerConfig = loggerConfigs.get(loggerName);
812 if (loggerConfig != null) {
813 return loggerConfig;
814 }
815 String substr = loggerName;
816 while ((substr = NameUtil.getSubName(substr)) != null) {
817 loggerConfig = loggerConfigs.get(substr);
818 if (loggerConfig != null) {
819 return loggerConfig;
820 }
821 }
822 return root;
823 }
824
825 @Override
826 public LoggerContext getLoggerContext() {
827 return loggerContext.get();
828 }
829
830
831
832
833
834
835 @Override
836 public LoggerConfig getRootLogger() {
837 return root;
838 }
839
840
841
842
843
844
845 @Override
846 public Map<String, LoggerConfig> getLoggers() {
847 return Collections.unmodifiableMap(loggerConfigs);
848 }
849
850
851
852
853
854
855
856 public LoggerConfig getLogger(final String loggerName) {
857 return loggerConfigs.get(loggerName);
858 }
859
860
861
862
863
864
865
866
867 @Override
868 public synchronized void addLogger(final String loggerName, final LoggerConfig loggerConfig) {
869 loggerConfigs.putIfAbsent(loggerName, loggerConfig);
870 setParents();
871 }
872
873
874
875
876
877
878 @Override
879 public synchronized void removeLogger(final String loggerName) {
880 loggerConfigs.remove(loggerName);
881 setParents();
882 }
883
884 @Override
885 public void createConfiguration(final Node node, final LogEvent event) {
886 final PluginType<?> type = node.getType();
887 if (type != null && type.isDeferChildren()) {
888 node.setObject(createPluginObject(type, node, event));
889 } else {
890 for (final Node child : node.getChildren()) {
891 createConfiguration(child, event);
892 }
893
894 if (type == null) {
895 if (node.getParent() != null) {
896 LOGGER.error("Unable to locate plugin for {}", node.getName());
897 }
898 } else {
899 node.setObject(createPluginObject(type, node, event));
900 }
901 }
902 }
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940 private Object createPluginObject(final PluginType<?> type, final Node node, final LogEvent event) {
941 final Class<?> clazz = type.getPluginClass();
942
943 if (Map.class.isAssignableFrom(clazz)) {
944 try {
945 return createPluginMap(node);
946 } catch (final Exception e) {
947 LOGGER.warn("Unable to create Map for {} of class {}", type.getElementName(), clazz, e);
948 }
949 }
950
951 if (Collection.class.isAssignableFrom(clazz)) {
952 try {
953 return createPluginCollection(node);
954 } catch (final Exception e) {
955 LOGGER.warn("Unable to create List for {} of class {}", type.getElementName(), clazz, e);
956 }
957 }
958
959 return new PluginBuilder(type).withConfiguration(this).withConfigurationNode(node).forLogEvent(event).build();
960 }
961
962 private static Map<String, ?> createPluginMap(final Node node) {
963 final Map<String, Object> map = new LinkedHashMap<>();
964 for (final Node child : node.getChildren()) {
965 final Object object = child.getObject();
966 map.put(child.getName(), object);
967 }
968 return map;
969 }
970
971 private static Collection<?> createPluginCollection(final Node node) {
972 final List<Node> children = node.getChildren();
973 final Collection<Object> list = new ArrayList<>(children.size());
974 for (final Node child : children) {
975 final Object object = child.getObject();
976 list.add(object);
977 }
978 return list;
979 }
980
981 private void setParents() {
982 for (final Map.Entry<String, LoggerConfig> entry : loggerConfigs.entrySet()) {
983 final LoggerConfig logger = entry.getValue();
984 String key = entry.getKey();
985 if (!key.isEmpty()) {
986 final int i = key.lastIndexOf('.');
987 if (i > 0) {
988 key = key.substring(0, i);
989 LoggerConfig parent = getLoggerConfig(key);
990 if (parent == null) {
991 parent = root;
992 }
993 logger.setParent(parent);
994 } else {
995 logger.setParent(root);
996 }
997 }
998 }
999 }
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009 protected static byte[] toByteArray(final InputStream is) throws IOException {
1010 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1011
1012 int nRead;
1013 final byte[] data = new byte[BUF_SIZE];
1014
1015 while ((nRead = is.read(data, 0, data.length)) != -1) {
1016 buffer.write(data, 0, nRead);
1017 }
1018
1019 return buffer.toByteArray();
1020 }
1021
1022 @Override
1023 public NanoClock getNanoClock() {
1024 return nanoClock;
1025 }
1026
1027 @Override
1028 public void setNanoClock(final NanoClock nanoClock) {
1029 this.nanoClock = Objects.requireNonNull(nanoClock, "nanoClock");
1030 }
1031 }