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> propertyMap = new ConcurrentHashMap<>();
126 private final StrLookup tempLookup = new Interpolator(propertyMap);
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, propertyMap);
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 propertyMap;
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 appenderName != null ? (T) appenders.get(appenderName) : null;
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 if (appender != null) {
670 appenders.putIfAbsent(appender.getName(), appender);
671 }
672 }
673
674 @Override
675 public StrSubstitutor getStrSubstitutor() {
676 return subst;
677 }
678
679 @Override
680 public void setAdvertiser(final Advertiser advertiser) {
681 this.advertiser = advertiser;
682 }
683
684 @Override
685 public Advertiser getAdvertiser() {
686 return advertiser;
687 }
688
689
690
691
692
693
694
695 @Override
696 public ReliabilityStrategy getReliabilityStrategy(final LoggerConfig loggerConfig) {
697 return ReliabilityStrategyFactory.getReliabilityStrategy(loggerConfig);
698 }
699
700
701
702
703
704
705
706
707
708
709 @Override
710 public synchronized void addLoggerAppender(final org.apache.logging.log4j.core.Logger logger,
711 final Appender appender) {
712 if (appender == null || logger == null) {
713 return;
714 }
715 final String loggerName = logger.getName();
716 appenders.putIfAbsent(appender.getName(), appender);
717 final LoggerConfig lc = getLoggerConfig(loggerName);
718 if (lc.getName().equals(loggerName)) {
719 lc.addAppender(appender, null, null);
720 } else {
721 final LoggerConfig nlc = new LoggerConfig(loggerName, lc.getLevel(), lc.isAdditive());
722 nlc.addAppender(appender, null, null);
723 nlc.setParent(lc);
724 loggerConfigs.putIfAbsent(loggerName, nlc);
725 setParents();
726 logger.getContext().updateLoggers();
727 }
728 }
729
730
731
732
733
734
735
736
737
738
739 @Override
740 public synchronized void addLoggerFilter(final org.apache.logging.log4j.core.Logger logger, final Filter filter) {
741 final String loggerName = logger.getName();
742 final LoggerConfig lc = getLoggerConfig(loggerName);
743 if (lc.getName().equals(loggerName)) {
744 lc.addFilter(filter);
745 } else {
746 final LoggerConfig nlc = new LoggerConfig(loggerName, lc.getLevel(), lc.isAdditive());
747 nlc.addFilter(filter);
748 nlc.setParent(lc);
749 loggerConfigs.putIfAbsent(loggerName, nlc);
750 setParents();
751 logger.getContext().updateLoggers();
752 }
753 }
754
755
756
757
758
759
760
761
762
763
764 @Override
765 public synchronized void setLoggerAdditive(final org.apache.logging.log4j.core.Logger logger, final boolean additive) {
766 final String loggerName = logger.getName();
767 final LoggerConfig lc = getLoggerConfig(loggerName);
768 if (lc.getName().equals(loggerName)) {
769 lc.setAdditive(additive);
770 } else {
771 final LoggerConfig nlc = new LoggerConfig(loggerName, lc.getLevel(), additive);
772 nlc.setParent(lc);
773 loggerConfigs.putIfAbsent(loggerName, nlc);
774 setParents();
775 logger.getContext().updateLoggers();
776 }
777 }
778
779
780
781
782
783
784
785
786 public synchronized void removeAppender(final String appenderName) {
787 for (final LoggerConfig logger : loggerConfigs.values()) {
788 logger.removeAppender(appenderName);
789 }
790 final Appender app = appenderName != null ? appenders.remove(appenderName) : null;
791
792 if (app != null) {
793 app.stop();
794 }
795 }
796
797
798
799
800
801
802 @Override
803 public List<CustomLevelConfig> getCustomLevels() {
804 return Collections.unmodifiableList(customLevels);
805 }
806
807
808
809
810
811
812
813
814 @Override
815 public LoggerConfig getLoggerConfig(final String loggerName) {
816 LoggerConfig loggerConfig = loggerConfigs.get(loggerName);
817 if (loggerConfig != null) {
818 return loggerConfig;
819 }
820 String substr = loggerName;
821 while ((substr = NameUtil.getSubName(substr)) != null) {
822 loggerConfig = loggerConfigs.get(substr);
823 if (loggerConfig != null) {
824 return loggerConfig;
825 }
826 }
827 return root;
828 }
829
830 @Override
831 public LoggerContext getLoggerContext() {
832 return loggerContext.get();
833 }
834
835
836
837
838
839
840 @Override
841 public LoggerConfig getRootLogger() {
842 return root;
843 }
844
845
846
847
848
849
850 @Override
851 public Map<String, LoggerConfig> getLoggers() {
852 return Collections.unmodifiableMap(loggerConfigs);
853 }
854
855
856
857
858
859
860
861 public LoggerConfig getLogger(final String loggerName) {
862 return loggerConfigs.get(loggerName);
863 }
864
865
866
867
868
869
870
871
872 @Override
873 public synchronized void addLogger(final String loggerName, final LoggerConfig loggerConfig) {
874 loggerConfigs.putIfAbsent(loggerName, loggerConfig);
875 setParents();
876 }
877
878
879
880
881
882
883 @Override
884 public synchronized void removeLogger(final String loggerName) {
885 loggerConfigs.remove(loggerName);
886 setParents();
887 }
888
889 @Override
890 public void createConfiguration(final Node node, final LogEvent event) {
891 final PluginType<?> type = node.getType();
892 if (type != null && type.isDeferChildren()) {
893 node.setObject(createPluginObject(type, node, event));
894 } else {
895 for (final Node child : node.getChildren()) {
896 createConfiguration(child, event);
897 }
898
899 if (type == null) {
900 if (node.getParent() != null) {
901 LOGGER.error("Unable to locate plugin for {}", node.getName());
902 }
903 } else {
904 node.setObject(createPluginObject(type, node, event));
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
941
942
943
944
945 private Object createPluginObject(final PluginType<?> type, final Node node, final LogEvent event) {
946 final Class<?> clazz = type.getPluginClass();
947
948 if (Map.class.isAssignableFrom(clazz)) {
949 try {
950 return createPluginMap(node);
951 } catch (final Exception e) {
952 LOGGER.warn("Unable to create Map for {} of class {}", type.getElementName(), clazz, e);
953 }
954 }
955
956 if (Collection.class.isAssignableFrom(clazz)) {
957 try {
958 return createPluginCollection(node);
959 } catch (final Exception e) {
960 LOGGER.warn("Unable to create List for {} of class {}", type.getElementName(), clazz, e);
961 }
962 }
963
964 return new PluginBuilder(type).withConfiguration(this).withConfigurationNode(node).forLogEvent(event).build();
965 }
966
967 private static Map<String, ?> createPluginMap(final Node node) {
968 final Map<String, Object> map = new LinkedHashMap<>();
969 for (final Node child : node.getChildren()) {
970 final Object object = child.getObject();
971 map.put(child.getName(), object);
972 }
973 return map;
974 }
975
976 private static Collection<?> createPluginCollection(final Node node) {
977 final List<Node> children = node.getChildren();
978 final Collection<Object> list = new ArrayList<>(children.size());
979 for (final Node child : children) {
980 final Object object = child.getObject();
981 list.add(object);
982 }
983 return list;
984 }
985
986 private void setParents() {
987 for (final Map.Entry<String, LoggerConfig> entry : loggerConfigs.entrySet()) {
988 final LoggerConfig logger = entry.getValue();
989 String key = entry.getKey();
990 if (!key.isEmpty()) {
991 final int i = key.lastIndexOf('.');
992 if (i > 0) {
993 key = key.substring(0, i);
994 LoggerConfig parent = getLoggerConfig(key);
995 if (parent == null) {
996 parent = root;
997 }
998 logger.setParent(parent);
999 } else {
1000 logger.setParent(root);
1001 }
1002 }
1003 }
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014 protected static byte[] toByteArray(final InputStream is) throws IOException {
1015 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
1016
1017 int nRead;
1018 final byte[] data = new byte[BUF_SIZE];
1019
1020 while ((nRead = is.read(data, 0, data.length)) != -1) {
1021 buffer.write(data, 0, nRead);
1022 }
1023
1024 return buffer.toByteArray();
1025 }
1026
1027 @Override
1028 public NanoClock getNanoClock() {
1029 return nanoClock;
1030 }
1031
1032 @Override
1033 public void setNanoClock(final NanoClock nanoClock) {
1034 this.nanoClock = Objects.requireNonNull(nanoClock, "nanoClock");
1035 }
1036 }