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