1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.xml;
19
20 import org.apache.log4j.Appender;
21 import org.apache.log4j.Layout;
22 import org.apache.log4j.Level;
23 import org.apache.log4j.LogManager;
24 import org.apache.log4j.Logger;
25 import org.apache.log4j.config.PropertySetter;
26 import org.apache.log4j.helpers.FileWatchdog;
27 import org.apache.log4j.helpers.Loader;
28 import org.apache.log4j.helpers.LogLog;
29 import org.apache.log4j.helpers.OptionConverter;
30 import org.apache.log4j.or.RendererMap;
31 import org.apache.log4j.spi.AppenderAttachable;
32 import org.apache.log4j.spi.Configurator;
33 import org.apache.log4j.spi.ErrorHandler;
34 import org.apache.log4j.spi.Filter;
35 import org.apache.log4j.spi.LoggerFactory;
36 import org.apache.log4j.spi.LoggerRepository;
37 import org.apache.log4j.spi.RendererSupport;
38 import org.apache.log4j.spi.ThrowableRenderer;
39 import org.apache.log4j.spi.ThrowableRendererSupport;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.NamedNodeMap;
43 import org.w3c.dom.Node;
44 import org.w3c.dom.NodeList;
45 import org.xml.sax.InputSource;
46 import org.xml.sax.SAXException;
47
48 import javax.xml.parsers.DocumentBuilder;
49 import javax.xml.parsers.DocumentBuilderFactory;
50 import javax.xml.parsers.FactoryConfigurationError;
51 import java.io.File;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.io.InterruptedIOException;
55 import java.io.Reader;
56 import java.lang.reflect.Method;
57 import java.lang.reflect.InvocationTargetException;
58 import java.net.URL;
59 import java.net.URLConnection;
60 import java.util.Hashtable;
61 import java.util.Properties;
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 public class DOMConfigurator implements Configurator {
91
92 static final String CONFIGURATION_TAG = "log4j:configuration";
93 static final String OLD_CONFIGURATION_TAG = "configuration";
94 static final String RENDERER_TAG = "renderer";
95 private static final String THROWABLE_RENDERER_TAG = "throwableRenderer";
96 static final String APPENDER_TAG = "appender";
97 static final String APPENDER_REF_TAG = "appender-ref";
98 static final String PARAM_TAG = "param";
99 static final String LAYOUT_TAG = "layout";
100 static final String CATEGORY = "category";
101 static final String LOGGER = "logger";
102 static final String LOGGER_REF = "logger-ref";
103 static final String CATEGORY_FACTORY_TAG = "categoryFactory";
104 static final String LOGGER_FACTORY_TAG = "loggerFactory";
105 static final String NAME_ATTR = "name";
106 static final String CLASS_ATTR = "class";
107 static final String VALUE_ATTR = "value";
108 static final String ROOT_TAG = "root";
109 static final String ROOT_REF = "root-ref";
110 static final String LEVEL_TAG = "level";
111 static final String PRIORITY_TAG = "priority";
112 static final String FILTER_TAG = "filter";
113 static final String ERROR_HANDLER_TAG = "errorHandler";
114 static final String REF_ATTR = "ref";
115 static final String ADDITIVITY_ATTR = "additivity";
116 static final String THRESHOLD_ATTR = "threshold";
117 static final String CONFIG_DEBUG_ATTR = "configDebug";
118 static final String INTERNAL_DEBUG_ATTR = "debug";
119 private static final String RESET_ATTR = "reset";
120 static final String RENDERING_CLASS_ATTR = "renderingClass";
121 static final String RENDERED_CLASS_ATTR = "renderedClass";
122
123 static final String EMPTY_STR = "";
124 static final Class[] ONE_STRING_PARAM = new Class[] {String.class};
125
126 final static String dbfKey = "javax.xml.parsers.DocumentBuilderFactory";
127
128
129
130 Hashtable appenderBag;
131
132 Properties props;
133 LoggerRepository repository;
134
135 protected LoggerFactory catFactory = null;
136
137
138
139
140 public
141 DOMConfigurator () {
142 appenderBag = new Hashtable();
143 }
144
145
146
147
148 protected
149 Appender findAppenderByName(Document doc, String appenderName) {
150 Appender appender = (Appender) appenderBag.get(appenderName);
151
152 if(appender != null) {
153 return appender;
154 } else {
155
156
157
158
159 Element element = null;
160 NodeList list = doc.getElementsByTagName("appender");
161 for (int t=0; t < list.getLength(); t++) {
162 Node node = list.item(t);
163 NamedNodeMap map= node.getAttributes();
164 Node attrNode = map.getNamedItem("name");
165 if (appenderName.equals(attrNode.getNodeValue())) {
166 element = (Element) node;
167 break;
168 }
169 }
170
171
172 if(element == null) {
173 LogLog.error("No appender named ["+appenderName+"] could be found.");
174 return null;
175 } else {
176 appender = parseAppender(element);
177 if (appender != null) {
178 appenderBag.put(appenderName, appender);
179 }
180 return appender;
181 }
182 }
183 }
184
185
186
187 protected
188 Appender findAppenderByReference(Element appenderRef) {
189 String appenderName = subst(appenderRef.getAttribute(REF_ATTR));
190 Document doc = appenderRef.getOwnerDocument();
191 return findAppenderByName(doc, appenderName);
192 }
193
194
195
196
197
198
199
200
201
202
203
204 private static void parseUnrecognizedElement(final Object instance,
205 final Element element,
206 final Properties props) throws Exception {
207 boolean recognized = false;
208 if (instance instanceof UnrecognizedElementHandler) {
209 recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
210 element, props);
211 }
212 if (!recognized) {
213 LogLog.warn("Unrecognized element " + element.getNodeName());
214 }
215 }
216
217
218
219
220
221
222
223
224
225
226 private static void quietParseUnrecognizedElement(final Object instance,
227 final Element element,
228 final Properties props) {
229 try {
230 parseUnrecognizedElement(instance, element, props);
231 } catch (Exception ex) {
232 if (ex instanceof InterruptedException || ex instanceof InterruptedIOException) {
233 Thread.currentThread().interrupt();
234 }
235 LogLog.error("Error in extension content: ", ex);
236 }
237 }
238
239
240
241
242 protected
243 Appender parseAppender (Element appenderElement) {
244 String className = subst(appenderElement.getAttribute(CLASS_ATTR));
245 LogLog.debug("Class name: [" + className+']');
246 try {
247 Object instance = Loader.loadClass(className).newInstance();
248 Appender appender = (Appender)instance;
249 PropertySetter propSetter = new PropertySetter(appender);
250
251 appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));
252
253 NodeList children = appenderElement.getChildNodes();
254 final int length = children.getLength();
255
256 for (int loop = 0; loop < length; loop++) {
257 Node currentNode = children.item(loop);
258
259
260 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
261 Element currentElement = (Element)currentNode;
262
263
264 if (currentElement.getTagName().equals(PARAM_TAG)) {
265 setParameter(currentElement, propSetter);
266 }
267
268 else if (currentElement.getTagName().equals(LAYOUT_TAG)) {
269 appender.setLayout(parseLayout(currentElement));
270 }
271
272 else if (currentElement.getTagName().equals(FILTER_TAG)) {
273 parseFilters(currentElement, appender);
274 }
275 else if (currentElement.getTagName().equals(ERROR_HANDLER_TAG)) {
276 parseErrorHandler(currentElement, appender);
277 }
278 else if (currentElement.getTagName().equals(APPENDER_REF_TAG)) {
279 String refName = subst(currentElement.getAttribute(REF_ATTR));
280 if(appender instanceof AppenderAttachable) {
281 AppenderAttachable aa = (AppenderAttachable) appender;
282 LogLog.debug("Attaching appender named ["+ refName+
283 "] to appender named ["+ appender.getName()+"].");
284 aa.addAppender(findAppenderByReference(currentElement));
285 } else {
286 LogLog.error("Requesting attachment of appender named ["+
287 refName+ "] to appender named ["+ appender.getName()+
288 "] which does not implement org.apache.log4j.spi.AppenderAttachable.");
289 }
290 } else {
291 parseUnrecognizedElement(instance, currentElement, props);
292 }
293 }
294 }
295 propSetter.activate();
296 return appender;
297 }
298
299
300 catch (Exception oops) {
301 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
302 Thread.currentThread().interrupt();
303 }
304 LogLog.error("Could not create an Appender. Reported error follows.",
305 oops);
306 return null;
307 }
308 }
309
310
311
312
313 protected
314 void parseErrorHandler(Element element, Appender appender) {
315 ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
316 subst(element.getAttribute(CLASS_ATTR)),
317 org.apache.log4j.spi.ErrorHandler.class,
318 null);
319
320 if(eh != null) {
321 eh.setAppender(appender);
322
323 PropertySetter propSetter = new PropertySetter(eh);
324 NodeList children = element.getChildNodes();
325 final int length = children.getLength();
326
327 for (int loop = 0; loop < length; loop++) {
328 Node currentNode = children.item(loop);
329 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
330 Element currentElement = (Element) currentNode;
331 String tagName = currentElement.getTagName();
332 if(tagName.equals(PARAM_TAG)) {
333 setParameter(currentElement, propSetter);
334 } else if(tagName.equals(APPENDER_REF_TAG)) {
335 eh.setBackupAppender(findAppenderByReference(currentElement));
336 } else if(tagName.equals(LOGGER_REF)) {
337 String loggerName = currentElement.getAttribute(REF_ATTR);
338 Logger logger = (catFactory == null) ? repository.getLogger(loggerName)
339 : repository.getLogger(loggerName, catFactory);
340 eh.setLogger(logger);
341 } else if(tagName.equals(ROOT_REF)) {
342 Logger root = repository.getRootLogger();
343 eh.setLogger(root);
344 } else {
345 quietParseUnrecognizedElement(eh, currentElement, props);
346 }
347 }
348 }
349 propSetter.activate();
350 appender.setErrorHandler(eh);
351 }
352 }
353
354
355
356
357 protected
358 void parseFilters(Element element, Appender appender) {
359 String clazz = subst(element.getAttribute(CLASS_ATTR));
360 Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz,
361 Filter.class, null);
362
363 if(filter != null) {
364 PropertySetter propSetter = new PropertySetter(filter);
365 NodeList children = element.getChildNodes();
366 final int length = children.getLength();
367
368 for (int loop = 0; loop < length; loop++) {
369 Node currentNode = children.item(loop);
370 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
371 Element currentElement = (Element) currentNode;
372 String tagName = currentElement.getTagName();
373 if(tagName.equals(PARAM_TAG)) {
374 setParameter(currentElement, propSetter);
375 } else {
376 quietParseUnrecognizedElement(filter, currentElement, props);
377 }
378 }
379 }
380 propSetter.activate();
381 LogLog.debug("Adding filter of type ["+filter.getClass()
382 +"] to appender named ["+appender.getName()+"].");
383 appender.addFilter(filter);
384 }
385 }
386
387
388
389
390 protected
391 void parseCategory (Element loggerElement) {
392
393 String catName = subst(loggerElement.getAttribute(NAME_ATTR));
394
395 Logger cat;
396
397 String className = subst(loggerElement.getAttribute(CLASS_ATTR));
398
399
400 if(EMPTY_STR.equals(className)) {
401 LogLog.debug("Retreiving an instance of org.apache.log4j.Logger.");
402 cat = (catFactory == null) ? repository.getLogger(catName) : repository.getLogger(catName, catFactory);
403 }
404 else {
405 LogLog.debug("Desired logger sub-class: ["+className+']');
406 try {
407 Class clazz = Loader.loadClass(className);
408 Method getInstanceMethod = clazz.getMethod("getLogger",
409 ONE_STRING_PARAM);
410 cat = (Logger) getInstanceMethod.invoke(null, new Object[] {catName});
411 } catch (InvocationTargetException oops) {
412 if (oops.getTargetException() instanceof InterruptedException
413 || oops.getTargetException() instanceof InterruptedIOException) {
414 Thread.currentThread().interrupt();
415 }
416 LogLog.error("Could not retrieve category ["+catName+
417 "]. Reported error follows.", oops);
418 return;
419 } catch (Exception oops) {
420 LogLog.error("Could not retrieve category ["+catName+
421 "]. Reported error follows.", oops);
422 return;
423 }
424 }
425
426
427
428
429 synchronized(cat) {
430 boolean additivity = OptionConverter.toBoolean(
431 subst(loggerElement.getAttribute(ADDITIVITY_ATTR)),
432 true);
433
434 LogLog.debug("Setting ["+cat.getName()+"] additivity to ["+additivity+"].");
435 cat.setAdditivity(additivity);
436 parseChildrenOfLoggerElement(loggerElement, cat, false);
437 }
438 }
439
440
441
442
443
444 protected
445 void parseCategoryFactory(Element factoryElement) {
446 String className = subst(factoryElement.getAttribute(CLASS_ATTR));
447
448 if(EMPTY_STR.equals(className)) {
449 LogLog.error("Category Factory tag " + CLASS_ATTR + " attribute not found.");
450 LogLog.debug("No Category Factory configured.");
451 }
452 else {
453 LogLog.debug("Desired category factory: ["+className+']');
454 Object factory = OptionConverter.instantiateByClassName(className,
455 LoggerFactory.class,
456 null);
457 if (factory instanceof LoggerFactory) {
458 catFactory = (LoggerFactory) factory;
459 } else {
460 LogLog.error("Category Factory class " + className + " does not implement org.apache.log4j.LoggerFactory");
461 }
462 PropertySetter propSetter = new PropertySetter(factory);
463
464 Element currentElement = null;
465 Node currentNode = null;
466 NodeList children = factoryElement.getChildNodes();
467 final int length = children.getLength();
468
469 for (int loop=0; loop < length; loop++) {
470 currentNode = children.item(loop);
471 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
472 currentElement = (Element)currentNode;
473 if (currentElement.getTagName().equals(PARAM_TAG)) {
474 setParameter(currentElement, propSetter);
475 } else {
476 quietParseUnrecognizedElement(factory, currentElement, props);
477 }
478 }
479 }
480 }
481 }
482
483
484
485
486
487 protected
488 void parseRoot (Element rootElement) {
489 Logger root = repository.getRootLogger();
490
491 synchronized(root) {
492 parseChildrenOfLoggerElement(rootElement, root, true);
493 }
494 }
495
496
497
498
499
500 protected
501 void parseChildrenOfLoggerElement(Element catElement,
502 Logger cat, boolean isRoot) {
503
504 PropertySetter propSetter = new PropertySetter(cat);
505
506
507
508 cat.removeAllAppenders();
509
510
511 NodeList children = catElement.getChildNodes();
512 final int length = children.getLength();
513
514 for (int loop = 0; loop < length; loop++) {
515 Node currentNode = children.item(loop);
516
517 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
518 Element currentElement = (Element) currentNode;
519 String tagName = currentElement.getTagName();
520
521 if (tagName.equals(APPENDER_REF_TAG)) {
522 Element appenderRef = (Element) currentNode;
523 Appender appender = findAppenderByReference(appenderRef);
524 String refName = subst(appenderRef.getAttribute(REF_ATTR));
525 if(appender != null)
526 LogLog.debug("Adding appender named ["+ refName+
527 "] to category ["+cat.getName()+"].");
528 else
529 LogLog.debug("Appender named ["+ refName + "] not found.");
530
531 cat.addAppender(appender);
532
533 } else if(tagName.equals(LEVEL_TAG)) {
534 parseLevel(currentElement, cat, isRoot);
535 } else if(tagName.equals(PRIORITY_TAG)) {
536 parseLevel(currentElement, cat, isRoot);
537 } else if(tagName.equals(PARAM_TAG)) {
538 setParameter(currentElement, propSetter);
539 } else {
540 quietParseUnrecognizedElement(cat, currentElement, props);
541 }
542 }
543 }
544 propSetter.activate();
545 }
546
547
548
549
550 protected
551 Layout parseLayout (Element layout_element) {
552 String className = subst(layout_element.getAttribute(CLASS_ATTR));
553 LogLog.debug("Parsing layout of class: \""+className+"\"");
554 try {
555 Object instance = Loader.loadClass(className).newInstance();
556 Layout layout = (Layout)instance;
557 PropertySetter propSetter = new PropertySetter(layout);
558
559 NodeList params = layout_element.getChildNodes();
560 final int length = params.getLength();
561
562 for (int loop = 0; loop < length; loop++) {
563 Node currentNode = (Node)params.item(loop);
564 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
565 Element currentElement = (Element) currentNode;
566 String tagName = currentElement.getTagName();
567 if(tagName.equals(PARAM_TAG)) {
568 setParameter(currentElement, propSetter);
569 } else {
570 parseUnrecognizedElement(instance, currentElement, props);
571 }
572 }
573 }
574
575 propSetter.activate();
576 return layout;
577 }
578 catch (Exception oops) {
579 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
580 Thread.currentThread().interrupt();
581 }
582 LogLog.error("Could not create the Layout. Reported error follows.",
583 oops);
584 return null;
585 }
586 }
587
588 protected
589 void parseRenderer(Element element) {
590 String renderingClass = subst(element.getAttribute(RENDERING_CLASS_ATTR));
591 String renderedClass = subst(element.getAttribute(RENDERED_CLASS_ATTR));
592 if(repository instanceof RendererSupport) {
593 RendererMap.addRenderer((RendererSupport) repository, renderedClass,
594 renderingClass);
595 }
596 }
597
598
599
600
601
602
603
604 protected ThrowableRenderer parseThrowableRenderer(final Element element) {
605 String className = subst(element.getAttribute(CLASS_ATTR));
606 LogLog.debug("Parsing throwableRenderer of class: \""+className+"\"");
607 try {
608 Object instance = Loader.loadClass(className).newInstance();
609 ThrowableRenderer tr = (ThrowableRenderer)instance;
610 PropertySetter propSetter = new PropertySetter(tr);
611
612 NodeList params = element.getChildNodes();
613 final int length = params.getLength();
614
615 for (int loop = 0; loop < length; loop++) {
616 Node currentNode = (Node)params.item(loop);
617 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
618 Element currentElement = (Element) currentNode;
619 String tagName = currentElement.getTagName();
620 if(tagName.equals(PARAM_TAG)) {
621 setParameter(currentElement, propSetter);
622 } else {
623 parseUnrecognizedElement(instance, currentElement, props);
624 }
625 }
626 }
627
628 propSetter.activate();
629 return tr;
630 }
631 catch (Exception oops) {
632 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
633 Thread.currentThread().interrupt();
634 }
635 LogLog.error("Could not create the ThrowableRenderer. Reported error follows.",
636 oops);
637 return null;
638 }
639 }
640
641
642
643
644 protected
645 void parseLevel(Element element, Logger logger, boolean isRoot) {
646 String catName = logger.getName();
647 if(isRoot) {
648 catName = "root";
649 }
650
651 String priStr = subst(element.getAttribute(VALUE_ATTR));
652 LogLog.debug("Level value for "+catName+" is ["+priStr+"].");
653
654 if(INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
655 if(isRoot) {
656 LogLog.error("Root level cannot be inherited. Ignoring directive.");
657 } else {
658 logger.setLevel(null);
659 }
660 } else {
661 String className = subst(element.getAttribute(CLASS_ATTR));
662 if(EMPTY_STR.equals(className)) {
663 logger.setLevel(OptionConverter.toLevel(priStr, Level.DEBUG));
664 } else {
665 LogLog.debug("Desired Level sub-class: ["+className+']');
666 try {
667 Class clazz = Loader.loadClass(className);
668 Method toLevelMethod = clazz.getMethod("toLevel",
669 ONE_STRING_PARAM);
670 Level pri = (Level) toLevelMethod.invoke(null,
671 new Object[] {priStr});
672 logger.setLevel(pri);
673 } catch (Exception oops) {
674 if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
675 Thread.currentThread().interrupt();
676 }
677 LogLog.error("Could not create level ["+priStr+
678 "]. Reported error follows.", oops);
679 return;
680 }
681 }
682 }
683 LogLog.debug(catName + " level set to " + logger.getLevel());
684 }
685
686 protected
687 void setParameter(Element elem, PropertySetter propSetter) {
688 String name = subst(elem.getAttribute(NAME_ATTR));
689 String value = (elem.getAttribute(VALUE_ATTR));
690 value = subst(OptionConverter.convertSpecialChars(value));
691 propSetter.setProperty(name, value);
692 }
693
694
695
696
697
698
699
700 static
701 public
702 void configure (Element element) {
703 DOMConfigurator configurator = new DOMConfigurator();
704 configurator.doConfigure(element, LogManager.getLoggerRepository());
705 }
706
707
708
709
710
711
712
713
714
715 static
716 public
717 void configureAndWatch(String configFilename) {
718 configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
719 }
720
721
722
723
724
725
726
727
728
729
730
731
732 static
733 public
734 void configureAndWatch(String configFilename, long delay) {
735 XMLWatchdog xdog = new XMLWatchdog(configFilename);
736 xdog.setDelay(delay);
737 xdog.start();
738 }
739
740 private interface ParseAction {
741 Document parse(final DocumentBuilder parser) throws SAXException, IOException;
742 }
743
744
745 public
746 void doConfigure(final String filename, LoggerRepository repository) {
747 ParseAction action = new ParseAction() {
748 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
749 return parser.parse(new File(filename));
750 }
751 public String toString() {
752 return "file [" + filename + "]";
753 }
754 };
755 doConfigure(action, repository);
756 }
757
758
759 public
760 void doConfigure(final URL url, LoggerRepository repository) {
761 ParseAction action = new ParseAction() {
762 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
763 URLConnection uConn = url.openConnection();
764 uConn.setUseCaches(false);
765 InputSource src = new InputSource(uConn.getInputStream());
766 src.setSystemId(url.toString());
767 return parser.parse(src);
768 }
769 public String toString() {
770 return "url [" + url.toString() + "]";
771 }
772 };
773 doConfigure(action, repository);
774 }
775
776
777
778
779
780
781 public
782 void doConfigure(final InputStream inputStream, LoggerRepository repository)
783 throws FactoryConfigurationError {
784 ParseAction action = new ParseAction() {
785 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
786 InputSource inputSource = new InputSource(inputStream);
787 inputSource.setSystemId("dummy://log4j.dtd");
788 return parser.parse(inputSource);
789 }
790 public String toString() {
791 return "input stream [" + inputStream.toString() + "]";
792 }
793 };
794 doConfigure(action, repository);
795 }
796
797
798
799
800
801
802 public
803 void doConfigure(final Reader reader, LoggerRepository repository)
804 throws FactoryConfigurationError {
805 ParseAction action = new ParseAction() {
806 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
807 InputSource inputSource = new InputSource(reader);
808 inputSource.setSystemId("dummy://log4j.dtd");
809 return parser.parse(inputSource);
810 }
811 public String toString() {
812 return "reader [" + reader.toString() + "]";
813 }
814 };
815 doConfigure(action, repository);
816 }
817
818
819
820
821
822
823 protected
824 void doConfigure(final InputSource inputSource, LoggerRepository repository)
825 throws FactoryConfigurationError {
826 if (inputSource.getSystemId() == null) {
827 inputSource.setSystemId("dummy://log4j.dtd");
828 }
829 ParseAction action = new ParseAction() {
830 public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
831 return parser.parse(inputSource);
832 }
833 public String toString() {
834 return "input source [" + inputSource.toString() + "]";
835 }
836 };
837 doConfigure(action, repository);
838 }
839
840
841 private final void doConfigure(final ParseAction action, final LoggerRepository repository)
842 throws FactoryConfigurationError {
843 DocumentBuilderFactory dbf = null;
844 this.repository = repository;
845 try {
846 LogLog.debug("System property is :"+
847 OptionConverter.getSystemProperty(dbfKey,
848 null));
849 dbf = DocumentBuilderFactory.newInstance();
850 LogLog.debug("Standard DocumentBuilderFactory search succeded.");
851 LogLog.debug("DocumentBuilderFactory is: "+dbf.getClass().getName());
852 } catch(FactoryConfigurationError fce) {
853 Exception e = fce.getException();
854 LogLog.debug("Could not instantiate a DocumentBuilderFactory.", e);
855 throw fce;
856 }
857
858 try {
859 dbf.setValidating(true);
860
861 DocumentBuilder docBuilder = dbf.newDocumentBuilder();
862
863 docBuilder.setErrorHandler(new SAXErrorHandler());
864 docBuilder.setEntityResolver(new Log4jEntityResolver());
865
866 Document doc = action.parse(docBuilder);
867 parse(doc.getDocumentElement());
868 } catch (Exception e) {
869 if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
870 Thread.currentThread().interrupt();
871 }
872
873 LogLog.error("Could not parse "+ action.toString() + ".", e);
874 }
875 }
876
877
878
879
880 public void doConfigure(Element element, LoggerRepository repository) {
881 this.repository = repository;
882 parse(element);
883 }
884
885
886
887
888 static
889 public
890 void configure(String filename) throws FactoryConfigurationError {
891 new DOMConfigurator().doConfigure(filename,
892 LogManager.getLoggerRepository());
893 }
894
895
896
897
898 static
899 public
900 void configure(URL url) throws FactoryConfigurationError {
901 new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
902 }
903
904
905
906
907
908
909
910 protected
911 void parse(Element element) {
912
913 String rootElementName = element.getTagName();
914
915 if (!rootElementName.equals(CONFIGURATION_TAG)) {
916 if(rootElementName.equals(OLD_CONFIGURATION_TAG)) {
917 LogLog.warn("The <"+OLD_CONFIGURATION_TAG+
918 "> element has been deprecated.");
919 LogLog.warn("Use the <"+CONFIGURATION_TAG+"> element instead.");
920 } else {
921 LogLog.error("DOM element is - not a <"+CONFIGURATION_TAG+"> element.");
922 return;
923 }
924 }
925
926
927 String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));
928
929 LogLog.debug("debug attribute= \"" + debugAttrib +"\".");
930
931
932 if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {
933 LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
934 } else {
935 LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
936 }
937
938
939
940
941
942 String resetAttrib = subst(element.getAttribute(RESET_ATTR));
943 LogLog.debug("reset attribute= \"" + resetAttrib +"\".");
944 if(!("".equals(resetAttrib))) {
945 if (OptionConverter.toBoolean(resetAttrib, false)) {
946 repository.resetConfiguration();
947 }
948 }
949
950
951
952 String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
953 if(!confDebug.equals("") && !confDebug.equals("null")) {
954 LogLog.warn("The \""+CONFIG_DEBUG_ATTR+"\" attribute is deprecated.");
955 LogLog.warn("Use the \""+INTERNAL_DEBUG_ATTR+"\" attribute instead.");
956 LogLog.setInternalDebugging(OptionConverter.toBoolean(confDebug, true));
957 }
958
959 String thresholdStr = subst(element.getAttribute(THRESHOLD_ATTR));
960 LogLog.debug("Threshold =\"" + thresholdStr +"\".");
961 if(!"".equals(thresholdStr) && !"null".equals(thresholdStr)) {
962 repository.setThreshold(thresholdStr);
963 }
964
965
966
967
968
969
970
971
972
973
974 String tagName = null;
975 Element currentElement = null;
976 Node currentNode = null;
977 NodeList children = element.getChildNodes();
978 final int length = children.getLength();
979
980 for (int loop = 0; loop < length; loop++) {
981 currentNode = children.item(loop);
982 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
983 currentElement = (Element) currentNode;
984 tagName = currentElement.getTagName();
985
986 if (tagName.equals(CATEGORY_FACTORY_TAG) || tagName.equals(LOGGER_FACTORY_TAG)) {
987 parseCategoryFactory(currentElement);
988 }
989 }
990 }
991
992 for (int loop = 0; loop < length; loop++) {
993 currentNode = children.item(loop);
994 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
995 currentElement = (Element) currentNode;
996 tagName = currentElement.getTagName();
997
998 if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
999 parseCategory(currentElement);
1000 } else if (tagName.equals(ROOT_TAG)) {
1001 parseRoot(currentElement);
1002 } else if(tagName.equals(RENDERER_TAG)) {
1003 parseRenderer(currentElement);
1004 } else if(tagName.equals(THROWABLE_RENDERER_TAG)) {
1005 if (repository instanceof ThrowableRendererSupport) {
1006 ThrowableRenderer tr = parseThrowableRenderer(currentElement);
1007 if (tr != null) {
1008 ((ThrowableRendererSupport) repository).setThrowableRenderer(tr);
1009 }
1010 }
1011 } else if (!(tagName.equals(APPENDER_TAG)
1012 || tagName.equals(CATEGORY_FACTORY_TAG)
1013 || tagName.equals(LOGGER_FACTORY_TAG))) {
1014 quietParseUnrecognizedElement(repository, currentElement, props);
1015 }
1016 }
1017 }
1018 }
1019
1020
1021 protected
1022 String subst(final String value) {
1023 return subst(value, props);
1024 }
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 public static String subst(final String value, final Properties props) {
1037 try {
1038 return OptionConverter.substVars(value, props);
1039 } catch (IllegalArgumentException e) {
1040 LogLog.warn("Could not perform variable substitution.", e);
1041 return value;
1042 }
1043 }
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054 public static void setParameter(final Element elem,
1055 final PropertySetter propSetter,
1056 final Properties props) {
1057 String name = subst(elem.getAttribute("name"), props);
1058 String value = (elem.getAttribute("value"));
1059 value = subst(OptionConverter.convertSpecialChars(value), props);
1060 propSetter.setProperty(name, value);
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077 public static Object parseElement(final Element element,
1078 final Properties props,
1079 final Class expectedClass) throws Exception {
1080 String clazz = subst(element.getAttribute("class"), props);
1081 Object instance = OptionConverter.instantiateByClassName(clazz,
1082 expectedClass, null);
1083
1084 if (instance != null) {
1085 PropertySetter propSetter = new PropertySetter(instance);
1086 NodeList children = element.getChildNodes();
1087 final int length = children.getLength();
1088
1089 for (int loop = 0; loop < length; loop++) {
1090 Node currentNode = children.item(loop);
1091 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
1092 Element currentElement = (Element) currentNode;
1093 String tagName = currentElement.getTagName();
1094 if (tagName.equals("param")) {
1095 setParameter(currentElement, propSetter, props);
1096 } else {
1097 parseUnrecognizedElement(instance, currentElement, props);
1098 }
1099 }
1100 }
1101 return instance;
1102 }
1103 return null;
1104 }
1105
1106 }
1107
1108
1109 class XMLWatchdog extends FileWatchdog {
1110
1111 XMLWatchdog(String filename) {
1112 super(filename);
1113 }
1114
1115
1116
1117
1118 public
1119 void doOnChange() {
1120 new DOMConfigurator().doConfigure(filename,
1121 LogManager.getLoggerRepository());
1122 }
1123 }