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