1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.xml;
18
19 import java.io.IOException;
20 import java.io.InterruptedIOException;
21 import java.lang.reflect.Method;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Properties;
25 import java.util.function.Consumer;
26
27 import javax.xml.parsers.DocumentBuilder;
28 import javax.xml.parsers.DocumentBuilderFactory;
29 import javax.xml.parsers.FactoryConfigurationError;
30
31 import org.apache.log4j.Appender;
32 import org.apache.log4j.Layout;
33 import org.apache.log4j.Level;
34 import org.apache.log4j.bridge.AppenderAdapter;
35 import org.apache.log4j.bridge.AppenderWrapper;
36 import org.apache.log4j.config.Log4j1Configuration;
37 import org.apache.log4j.config.PropertySetter;
38 import org.apache.log4j.helpers.OptionConverter;
39 import org.apache.log4j.rewrite.RewritePolicy;
40 import org.apache.log4j.spi.AppenderAttachable;
41 import org.apache.log4j.spi.ErrorHandler;
42 import org.apache.log4j.spi.Filter;
43 import org.apache.logging.log4j.core.LoggerContext;
44 import org.apache.logging.log4j.core.config.Configuration;
45 import org.apache.logging.log4j.core.config.ConfigurationSource;
46 import org.apache.logging.log4j.core.config.LoggerConfig;
47 import org.apache.logging.log4j.core.config.status.StatusConfiguration;
48 import org.apache.logging.log4j.status.StatusLogger;
49 import org.apache.logging.log4j.util.LoaderUtil;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.NamedNodeMap;
53 import org.w3c.dom.Node;
54 import org.w3c.dom.NodeList;
55 import org.xml.sax.InputSource;
56 import org.xml.sax.SAXException;
57 import org.xml.sax.SAXParseException;
58
59
60
61
62 public class XmlConfiguration extends Log4j1Configuration {
63
64 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
65
66 private static final String CONFIGURATION_TAG = "log4j:configuration";
67 private static final String OLD_CONFIGURATION_TAG = "configuration";
68 private static final String RENDERER_TAG = "renderer";
69 private static final String APPENDER_TAG = "appender";
70 public static final String PARAM_TAG = "param";
71 public static final String LAYOUT_TAG = "layout";
72 private static final String CATEGORY = "category";
73 private static final String LOGGER_ELEMENT = "logger";
74 private static final String CATEGORY_FACTORY_TAG = "categoryFactory";
75 private static final String LOGGER_FACTORY_TAG = "loggerFactory";
76 public static final String NAME_ATTR = "name";
77 private static final String CLASS_ATTR = "class";
78 public static final String VALUE_ATTR = "value";
79 private static final String ROOT_TAG = "root";
80 private static final String LEVEL_TAG = "level";
81 private static final String PRIORITY_TAG = "priority";
82 public static final String FILTER_TAG = "filter";
83 private static final String ERROR_HANDLER_TAG = "errorHandler";
84 public static final String REF_ATTR = "ref";
85 private static final String ADDITIVITY_ATTR = "additivity";
86 private static final String CONFIG_DEBUG_ATTR = "configDebug";
87 private static final String INTERNAL_DEBUG_ATTR = "debug";
88 private static final String EMPTY_STR = "";
89 private static final Class<?>[] ONE_STRING_PARAM = new Class[] { String.class };
90 private static final String dbfKey = "javax.xml.parsers.DocumentBuilderFactory";
91 private static final String THROWABLE_RENDERER_TAG = "throwableRenderer";
92
93 public static final long DEFAULT_DELAY = 60000;
94
95
96
97
98 protected static final String TEST_PREFIX = "log4j-test";
99
100
101
102
103 protected static final String DEFAULT_PREFIX = "log4j";
104
105
106 private Map<String, Appender> appenderMap;
107
108 private Properties props = null;
109
110 public XmlConfiguration(final LoggerContext loggerContext, final ConfigurationSource source,
111 int monitorIntervalSeconds) {
112 super(loggerContext, source, monitorIntervalSeconds);
113 appenderMap = new HashMap<>();
114 }
115
116 public void addAppenderIfAbsent(Appender appender) {
117 appenderMap.putIfAbsent(appender.getName(), appender);
118 }
119
120
121
122
123
124 @Override
125 public void doConfigure() throws FactoryConfigurationError {
126 ConfigurationSource source = getConfigurationSource();
127 ParseAction action = new ParseAction() {
128 @Override
129 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
130 @SuppressWarnings("resource")
131 InputSource inputSource = new InputSource(source.getInputStream());
132 inputSource.setSystemId("dummy://log4j.dtd");
133 return parser.parse(inputSource);
134 }
135
136 @Override
137 public String toString() {
138 return getConfigurationSource().getLocation();
139 }
140 };
141 doConfigure(action);
142 }
143
144 private void doConfigure(final ParseAction action) throws FactoryConfigurationError {
145 DocumentBuilderFactory dbf;
146 try {
147 LOGGER.debug("System property is : {}", OptionConverter.getSystemProperty(dbfKey, null));
148 dbf = DocumentBuilderFactory.newInstance();
149 LOGGER.debug("Standard DocumentBuilderFactory search succeded.");
150 LOGGER.debug("DocumentBuilderFactory is: " + dbf.getClass().getName());
151 } catch (FactoryConfigurationError fce) {
152 Exception e = fce.getException();
153 LOGGER.debug("Could not instantiate a DocumentBuilderFactory.", e);
154 throw fce;
155 }
156
157 try {
158 dbf.setValidating(true);
159
160 DocumentBuilder docBuilder = dbf.newDocumentBuilder();
161
162 docBuilder.setErrorHandler(new SAXErrorHandler());
163 docBuilder.setEntityResolver(new Log4jEntityResolver());
164
165 Document doc = action.parse(docBuilder);
166 parse(doc.getDocumentElement());
167 } catch (Exception e) {
168 if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
169 Thread.currentThread().interrupt();
170 }
171
172 LOGGER.error("Could not parse " + action.toString() + ".", e);
173 }
174 }
175
176 @Override
177 public Configuration reconfigure() {
178 try {
179 final ConfigurationSource source = getConfigurationSource().resetInputStream();
180 if (source == null) {
181 return null;
182 }
183 final XmlConfigurationFactory factory = new XmlConfigurationFactory();
184 final XmlConfiguration config =
185 (XmlConfiguration) factory.getConfiguration(getLoggerContext(), source);
186 return config == null || config.getState() != State.INITIALIZING ? null : config;
187 } catch (final IOException ex) {
188 LOGGER.error("Cannot locate file {}: {}", getConfigurationSource(), ex);
189 }
190 return null;
191 }
192
193
194
195
196
197
198
199
200
201 private void parseUnrecognizedElement(final Object instance, final Element element,
202 final Properties props) throws Exception {
203 boolean recognized = false;
204 if (instance instanceof UnrecognizedElementHandler) {
205 recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
206 element, props);
207 }
208 if (!recognized) {
209 LOGGER.warn("Unrecognized element {}", element.getNodeName());
210 }
211 }
212
213
214
215
216
217
218
219
220
221
222
223 private void quietParseUnrecognizedElement(final Object instance,
224 final Element element,
225 final Properties props) {
226 try {
227 parseUnrecognizedElement(instance, element, props);
228 } catch (Exception ex) {
229 if (ex instanceof InterruptedException || ex instanceof InterruptedIOException) {
230 Thread.currentThread().interrupt();
231 }
232 LOGGER.error("Error in extension content: ", ex);
233 }
234 }
235
236
237
238
239
240
241
242
243
244
245 public String subst(final String value, final Properties props) {
246 try {
247 return OptionConverter.substVars(value, props);
248 } catch (IllegalArgumentException e) {
249 LOGGER.warn("Could not perform variable substitution.", e);
250 return value;
251 }
252 }
253
254
255
256
257
258
259
260
261
262 public void setParameter(final Element elem, final PropertySetter propSetter, final Properties props) {
263 String name = subst(elem.getAttribute("name"), props);
264 String value = (elem.getAttribute("value"));
265 value = subst(OptionConverter.convertSpecialChars(value), props);
266 propSetter.setProperty(name, value);
267 }
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 public Object parseElement(final Element element, final Properties props,
284 @SuppressWarnings("rawtypes") final Class expectedClass) throws Exception {
285 String clazz = subst(element.getAttribute("class"), props);
286 Object instance = OptionConverter.instantiateByClassName(clazz,
287 expectedClass, null);
288
289 if (instance != null) {
290 PropertySetter propSetter = new PropertySetter(instance);
291 NodeList children = element.getChildNodes();
292 final int length = children.getLength();
293
294 for (int loop = 0; loop < length; loop++) {
295 Node currentNode = children.item(loop);
296 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
297 Element currentElement = (Element) currentNode;
298 String tagName = currentElement.getTagName();
299 if (tagName.equals("param")) {
300 setParameter(currentElement, propSetter, props);
301 } else {
302 parseUnrecognizedElement(instance, currentElement, props);
303 }
304 }
305 }
306 return instance;
307 }
308 return null;
309 }
310
311
312
313
314 private Appender findAppenderByName(Document doc, String appenderName) {
315 Appender appender = appenderMap.get(appenderName);
316
317 if (appender != null) {
318 return appender;
319 }
320
321 Element element = null;
322 NodeList list = doc.getElementsByTagName("appender");
323 for (int t = 0; t < list.getLength(); t++) {
324 Node node = list.item(t);
325 NamedNodeMap map = node.getAttributes();
326 Node attrNode = map.getNamedItem("name");
327 if (appenderName.equals(attrNode.getNodeValue())) {
328 element = (Element) node;
329 break;
330 }
331 }
332
333
334 if (element == null) {
335
336 LOGGER.error("No appender named [{}] could be found.", appenderName);
337 return null;
338 }
339 appender = parseAppender(element);
340 if (appender != null) {
341 appenderMap.put(appenderName, appender);
342 }
343 return appender;
344 }
345
346
347
348
349 public Appender findAppenderByReference(Element appenderRef) {
350 String appenderName = subst(appenderRef.getAttribute(REF_ATTR));
351 Document doc = appenderRef.getOwnerDocument();
352 return findAppenderByName(doc, appenderName);
353 }
354
355
356
357
358 public Appender parseAppender(Element appenderElement) {
359 String className = subst(appenderElement.getAttribute(CLASS_ATTR));
360 LOGGER.debug("Class name: [" + className + ']');
361 Appender appender = manager.parseAppender(className, appenderElement, this);
362 if (appender == null) {
363 appender = buildAppender(className, appenderElement);
364 }
365 return appender;
366 }
367
368 private Appender buildAppender(String className, Element appenderElement) {
369 try {
370 Appender appender = LoaderUtil.newInstanceOf(className);
371 PropertySetter propSetter = new PropertySetter(appender);
372
373 appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));
374 forEachElement(appenderElement.getChildNodes(), currentElement -> {
375
376 switch (currentElement.getTagName()) {
377 case PARAM_TAG:
378 setParameter(currentElement, propSetter);
379 break;
380 case LAYOUT_TAG:
381 appender.setLayout(parseLayout(currentElement));
382 break;
383 case FILTER_TAG:
384 Filter filter = parseFilters(currentElement);
385 if (filter != null) {
386 LOGGER.debug("Adding filter of type [{}] to appender named [{}]",
387 filter.getClass(), appender.getName());
388 appender.addFilter(filter);
389 }
390 break;
391 case ERROR_HANDLER_TAG:
392 parseErrorHandler(currentElement, appender);
393 break;
394 case APPENDER_REF_TAG:
395 String refName = subst(currentElement.getAttribute(REF_ATTR));
396 if (appender instanceof AppenderAttachable) {
397 AppenderAttachable aa = (AppenderAttachable) appender;
398 Appender child = findAppenderByReference(currentElement);
399 LOGGER.debug("Attaching appender named [{}] to appender named [{}].", refName,
400 appender.getName());
401 aa.addAppender(child);
402 } else {
403 LOGGER.error("Requesting attachment of appender named [{}] to appender named [{}]"
404 + "which does not implement org.apache.log4j.spi.AppenderAttachable.",
405 refName, appender.getName());
406 }
407 break;
408 default:
409 try {
410 parseUnrecognizedElement(appender, currentElement, props);
411 } catch (Exception ex) {
412 throw new ConsumerException(ex);
413 }
414 }
415 });
416 propSetter.activate();
417 return appender;
418 } catch (ConsumerException ex) {
419 Throwable t = ex.getCause();
420 if (t instanceof InterruptedException || t instanceof InterruptedIOException) {
421 Thread.currentThread().interrupt();
422 }
423 LOGGER.error("Could not create an Appender. Reported error follows.", t);
424 } catch (Exception oops) {
425 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
426 Thread.currentThread().interrupt();
427 }
428 LOGGER.error("Could not create an Appender. Reported error follows.", oops);
429 }
430 return null;
431 }
432
433 public RewritePolicy parseRewritePolicy(Element rewritePolicyElement) {
434 String className = subst(rewritePolicyElement.getAttribute(CLASS_ATTR));
435 LOGGER.debug("Class name: [" + className + ']');
436 RewritePolicy policy = manager.parseRewritePolicy(className, rewritePolicyElement, this);
437 if (policy == null) {
438 policy = buildRewritePolicy(className, rewritePolicyElement);
439 }
440 return policy;
441 }
442
443 private RewritePolicy buildRewritePolicy(String className, Element element) {
444 try {
445 RewritePolicy policy = LoaderUtil.newInstanceOf(className);
446 PropertySetter propSetter = new PropertySetter(policy);
447
448 forEachElement(element.getChildNodes(), currentElement -> {
449 if (currentElement.getTagName().equalsIgnoreCase(PARAM_TAG)) {
450 setParameter(currentElement, propSetter);
451 }
452 });
453 propSetter.activate();
454 return policy;
455 } catch (ConsumerException ex) {
456 Throwable t = ex.getCause();
457 if (t instanceof InterruptedException || t instanceof InterruptedIOException) {
458 Thread.currentThread().interrupt();
459 }
460 LOGGER.error("Could not create an RewritePolicy. Reported error follows.", t);
461 } catch (Exception oops) {
462 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
463 Thread.currentThread().interrupt();
464 }
465 LOGGER.error("Could not create an RewritePolicy. Reported error follows.", oops);
466 }
467 return null;
468 }
469
470
471
472
473 private void parseErrorHandler(Element element, Appender appender) {
474 ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
475 subst(element.getAttribute(CLASS_ATTR)),
476 ErrorHandler.class,
477 null);
478
479 if (eh != null) {
480 eh.setAppender(appender);
481
482 PropertySetter propSetter = new PropertySetter(eh);
483 forEachElement(element.getChildNodes(), currentElement -> {
484 String tagName = currentElement.getTagName();
485 if (tagName.equals(PARAM_TAG)) {
486 setParameter(currentElement, propSetter);
487 }
488 });
489 propSetter.activate();
490 appender.setErrorHandler(eh);
491 }
492 }
493
494
495
496
497 public Filter parseFilters(Element filterElement) {
498 String className = subst(filterElement.getAttribute(CLASS_ATTR));
499 LOGGER.debug("Class name: [" + className + ']');
500 Filter filter = manager.parseFilter(className, filterElement, this);
501 if (filter == null) {
502 PropertySetter propSetter = new PropertySetter(filter);
503 forEachElement(filterElement.getChildNodes(), currentElement -> {
504 String tagName = currentElement.getTagName();
505 if (tagName.equals(PARAM_TAG)) {
506 setParameter(currentElement, propSetter);
507 } else {
508 quietParseUnrecognizedElement(filter, currentElement, props);
509 }
510 });
511 propSetter.activate();
512 }
513 return filter;
514 }
515
516
517
518
519 private void parseCategory(Element loggerElement) {
520
521 String catName = subst(loggerElement.getAttribute(NAME_ATTR));
522 boolean additivity = OptionConverter.toBoolean(subst(loggerElement.getAttribute(ADDITIVITY_ATTR)), true);
523 LoggerConfig loggerConfig = getLogger(catName);
524 if (loggerConfig == null) {
525 loggerConfig = new LoggerConfig(catName, org.apache.logging.log4j.Level.ERROR, additivity);
526 addLogger(catName, loggerConfig);
527 } else {
528 loggerConfig.setAdditive(additivity);
529 }
530 parseChildrenOfLoggerElement(loggerElement, loggerConfig, false);
531 }
532
533
534
535
536 private void parseRoot(Element rootElement) {
537 LoggerConfig root = getRootLogger();
538 parseChildrenOfLoggerElement(rootElement, root, true);
539 }
540
541
542
543
544 private void parseChildrenOfLoggerElement(Element catElement, LoggerConfig loggerConfig, boolean isRoot) {
545
546 final PropertySetter propSetter = new PropertySetter(loggerConfig);
547 loggerConfig.getAppenderRefs().clear();
548 forEachElement(catElement.getChildNodes(), currentElement -> {
549 switch (currentElement.getTagName()) {
550 case APPENDER_REF_TAG: {
551 Appender appender = findAppenderByReference(currentElement);
552 String refName = subst(currentElement.getAttribute(REF_ATTR));
553 if (appender != null) {
554 LOGGER.debug("Adding appender named [{}] to loggerConfig [{}].", refName,
555 loggerConfig.getName());
556 loggerConfig.addAppender(getAppender(refName), null, null);
557 } else {
558 LOGGER.debug("Appender named [{}] not found.", refName);
559 }
560 break;
561 }
562 case LEVEL_TAG: case PRIORITY_TAG: {
563 parseLevel(currentElement, loggerConfig, isRoot);
564 break;
565 }
566 case PARAM_TAG: {
567 setParameter(currentElement, propSetter);
568 break;
569 }
570 default: {
571 quietParseUnrecognizedElement(loggerConfig, currentElement, props);
572 }
573 }
574 });
575 propSetter.activate();
576 }
577
578
579
580
581 public Layout parseLayout(Element layoutElement) {
582 String className = subst(layoutElement.getAttribute(CLASS_ATTR));
583 LOGGER.debug("Parsing layout of class: \"{}\"", className);
584 Layout layout = manager.parseLayout(className, layoutElement, this);
585 if (layout == null) {
586 layout = buildLayout(className, layoutElement);
587 }
588 return layout;
589 }
590
591 private Layout buildLayout(String className, Element layout_element) {
592 try {
593 Layout layout = LoaderUtil.newInstanceOf(className);
594 PropertySetter propSetter = new PropertySetter(layout);
595 forEachElement(layout_element.getChildNodes(), currentElement -> {
596 String tagName = currentElement.getTagName();
597 if (tagName.equals(PARAM_TAG)) {
598 setParameter(currentElement, propSetter);
599 } else {
600 try {
601 parseUnrecognizedElement(layout, currentElement, props);
602 } catch (Exception ex) {
603 throw new ConsumerException(ex);
604 }
605 }
606 });
607
608 propSetter.activate();
609 return layout;
610 } catch (ConsumerException ce) {
611 Throwable cause = ce.getCause();
612 if (cause instanceof InterruptedException || cause instanceof InterruptedIOException) {
613 Thread.currentThread().interrupt();
614 }
615 LOGGER.error("Could not create the Layout. Reported error follows.", cause);
616 } catch (Exception oops) {
617 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
618 Thread.currentThread().interrupt();
619 }
620 LOGGER.error("Could not create the Layout. Reported error follows.", oops);
621 }
622 return null;
623 }
624
625
626
627
628 private void parseLevel(Element element, LoggerConfig logger, boolean isRoot) {
629 String catName = logger.getName();
630 if (isRoot) {
631 catName = "root";
632 }
633
634 String priStr = subst(element.getAttribute(VALUE_ATTR));
635 LOGGER.debug("Level value for {} is [{}].", catName, priStr);
636
637 if (INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
638 if (isRoot) {
639 LOGGER.error("Root level cannot be inherited. Ignoring directive.");
640 } else {
641 logger.setLevel(null);
642 }
643 } else {
644 String className = subst(element.getAttribute(CLASS_ATTR));
645 if (EMPTY_STR.equals(className)) {
646 logger.setLevel(OptionConverter.convertLevel(priStr, org.apache.logging.log4j.Level.DEBUG));
647 } else {
648 LOGGER.debug("Desired Level sub-class: [{}]", className);
649 try {
650 Class<?> clazz = LoaderUtil.loadClass(className);
651 Method toLevelMethod = clazz.getMethod("toLevel", ONE_STRING_PARAM);
652 Level pri = (Level) toLevelMethod.invoke(null, priStr);
653 logger.setLevel(OptionConverter.convertLevel(pri));
654 } catch (Exception e) {
655 if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
656 Thread.currentThread().interrupt();
657 }
658 LOGGER.error("Could not create level [" + priStr +
659 "]. Reported error follows.", e);
660 return;
661 }
662 }
663 }
664 LOGGER.debug("{} level set to {}", catName, logger.getLevel());
665 }
666
667 private void setParameter(Element elem, PropertySetter propSetter) {
668 String name = subst(elem.getAttribute(NAME_ATTR));
669 String value = (elem.getAttribute(VALUE_ATTR));
670 value = subst(OptionConverter.convertSpecialChars(value));
671 propSetter.setProperty(name, value);
672 }
673
674
675
676
677
678
679 private void parse(Element element) {
680 String rootElementName = element.getTagName();
681
682 if (!rootElementName.equals(CONFIGURATION_TAG)) {
683 if (rootElementName.equals(OLD_CONFIGURATION_TAG)) {
684 LOGGER.warn("The <" + OLD_CONFIGURATION_TAG +
685 "> element has been deprecated.");
686 LOGGER.warn("Use the <" + CONFIGURATION_TAG + "> element instead.");
687 } else {
688 LOGGER.error("DOM element is - not a <" + CONFIGURATION_TAG + "> element.");
689 return;
690 }
691 }
692
693
694 String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));
695
696 LOGGER.debug("debug attribute= \"" + debugAttrib + "\".");
697
698
699 String status = "error";
700 if (!debugAttrib.equals("") && !debugAttrib.equals("null")) {
701 status = OptionConverter.toBoolean(debugAttrib, true) ? "debug" : "error";
702
703 } else {
704 LOGGER.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
705 }
706
707 String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
708 if (!confDebug.equals("") && !confDebug.equals("null")) {
709 LOGGER.warn("The \"" + CONFIG_DEBUG_ATTR + "\" attribute is deprecated.");
710 LOGGER.warn("Use the \"" + INTERNAL_DEBUG_ATTR + "\" attribute instead.");
711 status = OptionConverter.toBoolean(confDebug, true) ? "debug" : "error";
712 }
713
714 final StatusConfiguration statusConfig = new StatusConfiguration().withStatus(status);
715 statusConfig.initialize();
716
717 forEachElement(element.getChildNodes(), currentElement -> {
718 switch (currentElement.getTagName()) {
719 case CATEGORY:
720 case LOGGER_ELEMENT:
721 parseCategory(currentElement);
722 break;
723 case ROOT_TAG:
724 parseRoot(currentElement);
725 break;
726 case RENDERER_TAG:
727 LOGGER.warn("Renderers are not supported by Log4j 2 and will be ignored.");
728 break;
729 case THROWABLE_RENDERER_TAG:
730 LOGGER.warn("Throwable Renderers are not supported by Log4j 2 and will be ignored.");
731 break;
732 case CATEGORY_FACTORY_TAG:
733 case LOGGER_FACTORY_TAG:
734 LOGGER.warn("Log4j 1 Logger factories are not supported by Log4j 2 and will be ignored.");
735 break;
736 case APPENDER_TAG:
737 Appender appender = parseAppender(currentElement);
738 appenderMap.put(appender.getName(), appender);
739 if (appender instanceof AppenderWrapper) {
740 addAppender(((AppenderWrapper) appender).getAppender());
741 } else {
742 addAppender(new AppenderAdapter(appender).getAdapter());
743 }
744 break;
745 default:
746 quietParseUnrecognizedElement(null, currentElement, props);
747 }
748 });
749 }
750
751 private String subst(final String value) {
752 return getStrSubstitutor().replace(value);
753 }
754
755 public static void forEachElement(NodeList list, Consumer<Element> consumer) {
756 final int length = list.getLength();
757 for (int loop = 0; loop < length; loop++) {
758 Node currentNode = list.item(loop);
759
760 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
761 Element currentElement = (Element) currentNode;
762 consumer.accept(currentElement);
763 }
764 }
765 }
766
767 private interface ParseAction {
768 Document parse(final DocumentBuilder parser) throws SAXException, IOException;
769 }
770
771 private static class SAXErrorHandler implements org.xml.sax.ErrorHandler {
772 private static final org.apache.logging.log4j.Logger LOGGER = StatusLogger.getLogger();
773
774 @Override
775 public void error(final SAXParseException ex) {
776 emitMessage("Continuable parsing error ", ex);
777 }
778
779 @Override
780 public void fatalError(final SAXParseException ex) {
781 emitMessage("Fatal parsing error ", ex);
782 }
783
784 @Override
785 public void warning(final SAXParseException ex) {
786 emitMessage("Parsing warning ", ex);
787 }
788
789 private static void emitMessage(final String msg, final SAXParseException ex) {
790 LOGGER.warn("{} {} and column {}", msg, ex.getLineNumber(), ex.getColumnNumber());
791 LOGGER.warn(ex.getMessage(), ex.getException());
792 }
793 }
794
795 private static class ConsumerException extends RuntimeException {
796
797 ConsumerException(Exception ex) {
798 super(ex);
799 }
800 }
801 }