KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log4j > xml > DOMConfigurator


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.log4j.xml;
18
19 import java.util.*;
20
21 import java.net.URL JavaDoc;
22
23 import org.w3c.dom.*;
24 import java.lang.reflect.Method JavaDoc;
25 import org.apache.log4j.*;
26 import org.apache.log4j.spi.*;
27 import org.apache.log4j.or.RendererMap;
28 import org.apache.log4j.helpers.*;
29 import org.apache.log4j.config.PropertySetter;
30
31 import org.xml.sax.InputSource JavaDoc;
32 import java.io.FileInputStream JavaDoc;
33 import java.io.InputStream JavaDoc;
34 import java.io.Reader JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.net.URL JavaDoc;
37 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
38 import javax.xml.parsers.DocumentBuilder JavaDoc;
39 import javax.xml.parsers.FactoryConfigurationError JavaDoc;
40
41 // Contributors: Mark Womack
42
// Arun Katkere
43

44 /**
45    Use this class to initialize the log4j environment using a DOM tree.
46
47    <p>The DTD is specified in <a
48    href="doc-files/log4j.dtd"><b>log4j.dtd</b></a>.
49
50    <p>Sometimes it is useful to see how log4j is reading configuration
51    files. You can enable log4j internal logging by defining the
52    <b>log4j.debug</b> variable on the java command
53    line. Alternatively, set the <code>debug</code> attribute in the
54    <code>log4j:configuration</code> element. As in
55 <pre>
56    &lt;log4j:configuration <b>debug="true"</b> xmlns:log4j="http://jakarta.apache.org/log4j/">
57    ...
58    &lt;/log4j:configuration>
59 </pre>
60
61    <p>There are sample XML files included in the package.
62    
63    @author Christopher Taylor
64    @author Ceki G&uuml;lc&uuml;
65    @author Anders Kristensen
66
67    @since 0.8.3 */

68 public class DOMConfigurator implements Configurator {
69
70   static final String JavaDoc CONFIGURATION_TAG = "log4j:configuration";
71   static final String JavaDoc OLD_CONFIGURATION_TAG = "configuration";
72   static final String JavaDoc RENDERER_TAG = "renderer";
73   static final String JavaDoc APPENDER_TAG = "appender";
74   static final String JavaDoc APPENDER_REF_TAG = "appender-ref";
75   static final String JavaDoc PARAM_TAG = "param";
76   static final String JavaDoc LAYOUT_TAG = "layout";
77   static final String JavaDoc CATEGORY = "category";
78   static final String JavaDoc LOGGER = "logger";
79   static final String JavaDoc LOGGER_REF = "logger-ref";
80   static final String JavaDoc CATEGORY_FACTORY_TAG = "categoryFactory";
81   static final String JavaDoc NAME_ATTR = "name";
82   static final String JavaDoc CLASS_ATTR = "class";
83   static final String JavaDoc VALUE_ATTR = "value";
84   static final String JavaDoc ROOT_TAG = "root";
85   static final String JavaDoc ROOT_REF = "root-ref";
86   static final String JavaDoc LEVEL_TAG = "level";
87   static final String JavaDoc PRIORITY_TAG = "priority";
88   static final String JavaDoc FILTER_TAG = "filter";
89   static final String JavaDoc ERROR_HANDLER_TAG = "errorHandler";
90   static final String JavaDoc REF_ATTR = "ref";
91   static final String JavaDoc ADDITIVITY_ATTR = "additivity";
92   static final String JavaDoc THRESHOLD_ATTR = "threshold";
93   static final String JavaDoc CONFIG_DEBUG_ATTR = "configDebug";
94   static final String JavaDoc INTERNAL_DEBUG_ATTR = "debug";
95   static final String JavaDoc RENDERING_CLASS_ATTR = "renderingClass";
96   static final String JavaDoc RENDERED_CLASS_ATTR = "renderedClass";
97
98   static final String JavaDoc EMPTY_STR = "";
99   static final Class JavaDoc[] ONE_STRING_PARAM = new Class JavaDoc[] {String JavaDoc.class};
100
101   final static String JavaDoc dbfKey = "javax.xml.parsers.DocumentBuilderFactory";
102
103   
104   // key: appenderName, value: appender
105
Hashtable appenderBag;
106
107   Properties props;
108   LoggerRepository repository;
109
110   /**
111      No argument constructor.
112   */

113   public
114   DOMConfigurator () {
115     appenderBag = new Hashtable();
116   }
117
118   /**
119      Used internally to parse appenders by IDREF name.
120   */

121   protected
122   Appender findAppenderByName(Document doc, String JavaDoc appenderName) {
123     Appender appender = (Appender) appenderBag.get(appenderName);
124
125     if(appender != null) {
126       return appender;
127     } else {
128       // Doesn't work on DOM Level 1 :
129
// Element element = doc.getElementById(appenderName);
130

131       // Endre's hack:
132
Element element = null;
133       NodeList list = doc.getElementsByTagName("appender");
134       for (int t=0; t < list.getLength(); t++) {
135     Node node = list.item(t);
136     NamedNodeMap map= node.getAttributes();
137     Node attrNode = map.getNamedItem("name");
138     if (appenderName.equals(attrNode.getNodeValue())) {
139       element = (Element) node;
140       break;
141     }
142       }
143       // Hack finished.
144

145       if(element == null) {
146     LogLog.error("No appender named ["+appenderName+"] could be found.");
147     return null;
148       } else {
149     appender = parseAppender(element);
150     appenderBag.put(appenderName, appender);
151     return appender;
152       }
153     }
154   }
155   /**
156      Used internally to parse appenders by IDREF element.
157    */

158   protected
159   Appender findAppenderByReference(Element appenderRef) {
160     String JavaDoc appenderName = subst(appenderRef.getAttribute(REF_ATTR));
161     Document doc = appenderRef.getOwnerDocument();
162     return findAppenderByName(doc, appenderName);
163   }
164
165   /**
166      Used internally to parse an appender element.
167    */

168   protected
169   Appender parseAppender (Element appenderElement) {
170     String JavaDoc className = subst(appenderElement.getAttribute(CLASS_ATTR));
171     LogLog.debug("Class name: [" + className+']');
172     try {
173       Object JavaDoc instance = Loader.loadClass(className).newInstance();
174       Appender appender = (Appender)instance;
175       PropertySetter propSetter = new PropertySetter(appender);
176
177       appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));
178       
179       NodeList children = appenderElement.getChildNodes();
180       final int length = children.getLength();
181
182       for (int loop = 0; loop < length; loop++) {
183     Node currentNode = children.item(loop);
184
185     /* We're only interested in Elements */
186     if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
187       Element currentElement = (Element)currentNode;
188
189       // Parse appender parameters
190
if (currentElement.getTagName().equals(PARAM_TAG)) {
191             setParameter(currentElement, propSetter);
192       }
193       // Set appender layout
194
else if (currentElement.getTagName().equals(LAYOUT_TAG)) {
195         appender.setLayout(parseLayout(currentElement));
196       }
197       // Add filters
198
else if (currentElement.getTagName().equals(FILTER_TAG)) {
199         parseFilters(currentElement, appender);
200       }
201       else if (currentElement.getTagName().equals(ERROR_HANDLER_TAG)) {
202         parseErrorHandler(currentElement, appender);
203       }
204       else if (currentElement.getTagName().equals(APPENDER_REF_TAG)) {
205         String JavaDoc refName = subst(currentElement.getAttribute(REF_ATTR));
206         if(appender instanceof AppenderAttachable) {
207           AppenderAttachable aa = (AppenderAttachable) appender;
208           LogLog.debug("Attaching appender named ["+ refName+
209                "] to appender named ["+ appender.getName()+"].");
210           aa.addAppender(findAppenderByReference(currentElement));
211         } else {
212           LogLog.error("Requesting attachment of appender named ["+
213                refName+ "] to appender named ["+ appender.getName()+
214                 "] which does not implement org.apache.log4j.spi.AppenderAttachable.");
215         }
216       }
217     }
218       }
219       propSetter.activate();
220       return appender;
221     }
222     /* Yes, it's ugly. But all of these exceptions point to the same
223        problem: we can't create an Appender */

224     catch (Exception JavaDoc oops) {
225       LogLog.error("Could not create an Appender. Reported error follows.",
226            oops);
227       return null;
228     }
229   }
230
231   /**
232      Used internally to parse an {@link ErrorHandler} element.
233    */

234   protected
235   void parseErrorHandler(Element element, Appender appender) {
236     ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
237                                        subst(element.getAttribute(CLASS_ATTR)),
238                                        org.apache.log4j.spi.ErrorHandler.class,
239                        null);
240     
241     if(eh != null) {
242       eh.setAppender(appender);
243
244       PropertySetter propSetter = new PropertySetter(eh);
245       NodeList children = element.getChildNodes();
246       final int length = children.getLength();
247
248       for (int loop = 0; loop < length; loop++) {
249     Node currentNode = children.item(loop);
250     if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
251       Element currentElement = (Element) currentNode;
252       String JavaDoc tagName = currentElement.getTagName();
253       if(tagName.equals(PARAM_TAG)) {
254             setParameter(currentElement, propSetter);
255       } else if(tagName.equals(APPENDER_REF_TAG)) {
256         eh.setBackupAppender(findAppenderByReference(currentElement));
257       } else if(tagName.equals(LOGGER_REF)) {
258         String JavaDoc loggerName = currentElement.getAttribute(REF_ATTR);
259         Logger logger = repository.getLogger(loggerName);
260         eh.setLogger(logger);
261       } else if(tagName.equals(ROOT_REF)) {
262         Logger root = repository.getRootLogger();
263         eh.setLogger(root);
264       }
265     }
266       }
267       propSetter.activate();
268       appender.setErrorHandler(eh);
269     }
270   }
271   
272   /**
273      Used internally to parse a filter element.
274    */

275   protected
276   void parseFilters(Element element, Appender appender) {
277     String JavaDoc clazz = subst(element.getAttribute(CLASS_ATTR));
278     Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz,
279                                                 Filter.class, null);
280     
281     if(filter != null) {
282       PropertySetter propSetter = new PropertySetter(filter);
283       NodeList children = element.getChildNodes();
284       final int length = children.getLength();
285
286       for (int loop = 0; loop < length; loop++) {
287     Node currentNode = children.item(loop);
288     if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
289       Element currentElement = (Element) currentNode;
290       String JavaDoc tagName = currentElement.getTagName();
291       if(tagName.equals(PARAM_TAG)) {
292             setParameter(currentElement, propSetter);
293       }
294     }
295       }
296       propSetter.activate();
297       LogLog.debug("Adding filter of type ["+filter.getClass()
298            +"] to appender named ["+appender.getName()+"].");
299       appender.addFilter(filter);
300     }
301   }
302   
303   /**
304      Used internally to parse an category element.
305   */

306   protected
307   void parseCategory (Element loggerElement) {
308     // Create a new org.apache.log4j.Category object from the <category> element.
309
String JavaDoc catName = subst(loggerElement.getAttribute(NAME_ATTR));
310
311     Logger cat;
312
313     String JavaDoc className = subst(loggerElement.getAttribute(CLASS_ATTR));
314
315
316     if(EMPTY_STR.equals(className)) {
317       LogLog.debug("Retreiving an instance of org.apache.log4j.Logger.");
318       cat = repository.getLogger(catName);
319     }
320     else {
321       LogLog.debug("Desired logger sub-class: ["+className+']');
322        try {
323      Class JavaDoc clazz = Loader.loadClass(className);
324      Method JavaDoc getInstanceMethod = clazz.getMethod("getLogger",
325                             ONE_STRING_PARAM);
326      cat = (Logger) getInstanceMethod.invoke(null, new Object JavaDoc[] {catName});
327        } catch (Exception JavaDoc oops) {
328      LogLog.error("Could not retrieve category ["+catName+
329               "]. Reported error follows.", oops);
330      return;
331        }
332     }
333
334     // Setting up a category needs to be an atomic operation, in order
335
// to protect potential log operations while category
336
// configuration is in progress.
337
synchronized(cat) {
338       boolean additivity = OptionConverter.toBoolean(
339                            subst(loggerElement.getAttribute(ADDITIVITY_ATTR)),
340                true);
341     
342       LogLog.debug("Setting ["+cat.getName()+"] additivity to ["+additivity+"].");
343       cat.setAdditivity(additivity);
344       parseChildrenOfLoggerElement(loggerElement, cat, false);
345     }
346   }
347
348
349   /**
350      Used internally to parse the category factory element.
351   */

352   protected
353   void parseCategoryFactory(Element factoryElement) {
354     String JavaDoc className = subst(factoryElement.getAttribute(CLASS_ATTR));
355
356     if(EMPTY_STR.equals(className)) {
357       LogLog.error("Category Factory tag " + CLASS_ATTR + " attribute not found.");
358       LogLog.debug("No Category Factory configured.");
359     }
360     else {
361       LogLog.debug("Desired category factory: ["+className+']');
362       Object JavaDoc catFactory = OptionConverter.instantiateByClassName(className,
363                                                                  LoggerFactory.class,
364                                                                  null);
365       PropertySetter propSetter = new PropertySetter(catFactory);
366
367       Element currentElement = null;
368       Node currentNode = null;
369       NodeList children = factoryElement.getChildNodes();
370       final int length = children.getLength();
371
372       for (int loop=0; loop < length; loop++) {
373         currentNode = children.item(loop);
374     if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
375       currentElement = (Element)currentNode;
376       if (currentElement.getTagName().equals(PARAM_TAG)) {
377         setParameter(currentElement, propSetter);
378       }
379     }
380       }
381     }
382   }
383
384
385   /**
386      Used internally to parse the roor category element.
387   */

388   protected
389   void parseRoot (Element rootElement) {
390     Logger root = repository.getRootLogger();
391     // category configuration needs to be atomic
392
synchronized(root) {
393       parseChildrenOfLoggerElement(rootElement, root, true);
394     }
395   }
396
397
398   /**
399      Used internally to parse the children of a category element.
400   */

401   protected
402   void parseChildrenOfLoggerElement(Element catElement,
403                       Logger cat, boolean isRoot) {
404     
405     PropertySetter propSetter = new PropertySetter(cat);
406     
407     // Remove all existing appenders from cat. They will be
408
// reconstructed if need be.
409
cat.removeAllAppenders();
410
411
412     NodeList children = catElement.getChildNodes();
413     final int length = children.getLength();
414     
415     for (int loop = 0; loop < length; loop++) {
416       Node currentNode = children.item(loop);
417
418       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
419     Element currentElement = (Element) currentNode;
420     String JavaDoc tagName = currentElement.getTagName();
421     
422     if (tagName.equals(APPENDER_REF_TAG)) {
423       Element appenderRef = (Element) currentNode;
424       Appender appender = findAppenderByReference(appenderRef);
425       String JavaDoc refName = subst(appenderRef.getAttribute(REF_ATTR));
426       if(appender != null)
427         LogLog.debug("Adding appender named ["+ refName+
428              "] to category ["+cat.getName()+"].");
429       else
430         LogLog.debug("Appender named ["+ refName + "] not found.");
431         
432       cat.addAppender(appender);
433       
434     } else if(tagName.equals(LEVEL_TAG)) {
435       parseLevel(currentElement, cat, isRoot);
436     } else if(tagName.equals(PRIORITY_TAG)) {
437       parseLevel(currentElement, cat, isRoot);
438     } else if(tagName.equals(PARAM_TAG)) {
439           setParameter(currentElement, propSetter);
440     }
441       }
442     }
443     propSetter.activate();
444   }
445
446   /**
447      Used internally to parse a layout element.
448   */

449   protected
450   Layout parseLayout (Element layout_element) {
451     String JavaDoc className = subst(layout_element.getAttribute(CLASS_ATTR));
452     LogLog.debug("Parsing layout of class: \""+className+"\"");
453     try {
454       Object JavaDoc instance = Loader.loadClass(className).newInstance();
455       Layout layout = (Layout)instance;
456       PropertySetter propSetter = new PropertySetter(layout);
457       
458       NodeList params = layout_element.getChildNodes();
459       final int length = params.getLength();
460
461       for (int loop = 0; loop < length; loop++) {
462     Node currentNode = (Node)params.item(loop);
463     if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
464       Element currentElement = (Element) currentNode;
465       String JavaDoc tagName = currentElement.getTagName();
466       if(tagName.equals(PARAM_TAG)) {
467             setParameter(currentElement, propSetter);
468       }
469     }
470       }
471       
472       propSetter.activate();
473       return layout;
474     }
475     catch (Exception JavaDoc oops) {
476       LogLog.error("Could not create the Layout. Reported error follows.",
477            oops);
478       return null;
479     }
480   }
481
482   protected
483   void parseRenderer(Element element) {
484     String JavaDoc renderingClass = subst(element.getAttribute(RENDERING_CLASS_ATTR));
485     String JavaDoc renderedClass = subst(element.getAttribute(RENDERED_CLASS_ATTR));
486     if(repository instanceof RendererSupport) {
487       RendererMap.addRenderer((RendererSupport) repository, renderedClass,
488                   renderingClass);
489     }
490   }
491
492   /**
493      Used internally to parse a level element.
494   */

495   protected
496   void parseLevel(Element element, Logger logger, boolean isRoot) {
497     String JavaDoc catName = logger.getName();
498     if(isRoot) {
499       catName = "root";
500     }
501
502     String JavaDoc priStr = subst(element.getAttribute(VALUE_ATTR));
503     LogLog.debug("Level value for "+catName+" is ["+priStr+"].");
504     
505     if(INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
506       if(isRoot) {
507     LogLog.error("Root level cannot be inherited. Ignoring directive.");
508       } else {
509     logger.setLevel(null);
510       }
511     } else {
512       String JavaDoc className = subst(element.getAttribute(CLASS_ATTR));
513       if(EMPTY_STR.equals(className)) {
514     logger.setLevel(OptionConverter.toLevel(priStr, Level.DEBUG));
515       } else {
516     LogLog.debug("Desired Level sub-class: ["+className+']');
517     try {
518       Class JavaDoc clazz = Loader.loadClass(className);
519       Method JavaDoc toLevelMethod = clazz.getMethod("toLevel",
520                             ONE_STRING_PARAM);
521       Level pri = (Level) toLevelMethod.invoke(null,
522                             new Object JavaDoc[] {priStr});
523       logger.setLevel(pri);
524     } catch (Exception JavaDoc oops) {
525       LogLog.error("Could not create level ["+priStr+
526                "]. Reported error follows.", oops);
527       return;
528     }
529       }
530     }
531     LogLog.debug(catName + " level set to " + logger.getLevel());
532   }
533
534   protected
535   void setParameter(Element elem, PropertySetter propSetter) {
536     String JavaDoc name = subst(elem.getAttribute(NAME_ATTR));
537     String JavaDoc value = (elem.getAttribute(VALUE_ATTR));
538     value = subst(OptionConverter.convertSpecialChars(value));
539     propSetter.setProperty(name, value);
540   }
541
542
543   /**
544      Configure log4j using a <code>configuration</code> element as
545      defined in the log4j.dtd.
546
547   */

548   static
549   public
550   void configure (Element element) {
551     DOMConfigurator configurator = new DOMConfigurator();
552     configurator.doConfigure(element, LogManager.getLoggerRepository());
553   }
554
555  /**
556      Like {@link #configureAndWatch(String, long)} except that the
557      default delay as defined by {@link FileWatchdog#DEFAULT_DELAY} is
558      used.
559
560      @param configFilename A log4j configuration file in XML format.
561
562   */

563   static
564   public
565   void configureAndWatch(String JavaDoc configFilename) {
566     configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
567   }
568
569   /**
570      Read the configuration file <code>configFilename</code> if it
571      exists. Moreover, a thread will be created that will periodically
572      check if <code>configFilename</code> has been created or
573      modified. The period is determined by the <code>delay</code>
574      argument. If a change or file creation is detected, then
575      <code>configFilename</code> is read to configure log4j.
576
577       @param configFilename A log4j configuration file in XML format.
578       @param delay The delay in milliseconds to wait between each check.
579   */

580   static
581   public
582   void configureAndWatch(String JavaDoc configFilename, long delay) {
583     XMLWatchdog xdog = new XMLWatchdog(configFilename);
584     xdog.setDelay(delay);
585     xdog.start();
586   }
587
588   public
589   void doConfigure(String JavaDoc filename, LoggerRepository repository) {
590     FileInputStream JavaDoc fis = null;
591     try {
592       fis = new FileInputStream JavaDoc(filename);
593       doConfigure(fis, repository);
594     } catch(IOException JavaDoc e) {
595       LogLog.error("Could not open ["+filename+"].", e);
596     } finally {
597       if (fis != null) {
598     try {
599       fis.close();
600     } catch(java.io.IOException JavaDoc e) {
601       LogLog.error("Could not close ["+filename+"].", e);
602     }
603       }
604     }
605   }
606   
607
608   public
609   void doConfigure(URL JavaDoc url, LoggerRepository repository) {
610     try {
611       doConfigure(url.openStream(), repository);
612     } catch(IOException JavaDoc e) {
613       LogLog.error("Could not open ["+url+"].", e);
614     }
615   }
616
617   /**
618      Configure log4j by reading in a log4j.dtd compliant XML
619      configuration file.
620
621   */

622   public
623   void doConfigure(InputStream JavaDoc inputStream, LoggerRepository repository)
624                                           throws FactoryConfigurationError JavaDoc {
625     doConfigure(new InputSource JavaDoc(inputStream), repository);
626   }
627
628   /**
629      Configure log4j by reading in a log4j.dtd compliant XML
630      configuration file.
631
632   */

633   public
634   void doConfigure(Reader JavaDoc reader, LoggerRepository repository)
635                                           throws FactoryConfigurationError JavaDoc {
636     doConfigure(new InputSource JavaDoc(reader), repository);
637   }
638
639   /**
640      Configure log4j by reading in a log4j.dtd compliant XML
641      configuration file.
642
643   */

644   protected
645   void doConfigure(InputSource JavaDoc inputSource, LoggerRepository repository)
646                                           throws FactoryConfigurationError JavaDoc {
647     DocumentBuilderFactory JavaDoc dbf = null;
648     this.repository = repository;
649     try {
650       LogLog.debug("System property is :"+
651                             OptionConverter.getSystemProperty(dbfKey,
652                                   null));
653       dbf = DocumentBuilderFactory.newInstance();
654       LogLog.debug("Standard DocumentBuilderFactory search succeded.");
655       LogLog.debug("DocumentBuilderFactory is: "+dbf.getClass().getName());
656     } catch(FactoryConfigurationError JavaDoc fce) {
657       Exception JavaDoc e = fce.getException();
658       LogLog.debug("Could not instantiate a DocumentBuilderFactory.", e);
659       throw fce;
660     }
661       
662     try {
663       dbf.setValidating(true);
664
665       DocumentBuilder JavaDoc docBuilder = dbf.newDocumentBuilder();
666
667       docBuilder.setErrorHandler(new SAXErrorHandler());
668       docBuilder.setEntityResolver(new Log4jEntityResolver());
669       // we change the system ID to a valid URI so that Crimson won't
670
// complain. Indeed, "log4j.dtd" alone is not a valid URI which
671
// causes Crimson to barf. The Log4jEntityResolver only cares
672
// about the "log4j.dtd" ending.
673
inputSource.setSystemId("dummy://log4j.dtd");
674       Document doc = docBuilder.parse(inputSource);
675       parse(doc.getDocumentElement());
676     } catch (Exception JavaDoc e) {
677       // I know this is miserable...
678
LogLog.error("Could not parse input source ["+inputSource+"].", e);
679     }
680   }
681
682   /**
683      Configure by taking in an DOM element.
684   */

685   public void doConfigure(Element element, LoggerRepository repository) {
686     this.repository = repository;
687     parse(element);
688   }
689
690   
691   /**
692      A static version of {@link #doConfigure(String, LoggerRepository)}. */

693   static
694   public
695   void configure(String JavaDoc filename) throws FactoryConfigurationError JavaDoc {
696     new DOMConfigurator().doConfigure(filename,
697                       LogManager.getLoggerRepository());
698   }
699
700   /**
701      A static version of {@link #doConfigure(URL, LoggerRepository)}.
702    */

703   static
704   public
705   void configure(URL JavaDoc url) throws FactoryConfigurationError JavaDoc {
706     new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
707   }
708
709   /**
710      Used internally to configure the log4j framework by parsing a DOM
711      tree of XML elements based on <a
712      href="doc-files/log4j.dtd">log4j.dtd</a>.
713      
714   */

715   protected
716   void parse(Element element) {
717
718     String JavaDoc rootElementName = element.getTagName();
719
720     if (!rootElementName.equals(CONFIGURATION_TAG)) {
721       if(rootElementName.equals(OLD_CONFIGURATION_TAG)) {
722     LogLog.warn("The <"+OLD_CONFIGURATION_TAG+
723              "> element has been deprecated.");
724     LogLog.warn("Use the <"+CONFIGURATION_TAG+"> element instead.");
725       } else {
726     LogLog.error("DOM element is - not a <"+CONFIGURATION_TAG+"> element.");
727     return;
728       }
729     }
730
731     String JavaDoc debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));
732       
733     LogLog.debug("debug attribute= \"" + debugAttrib +"\".");
734     // if the log4j.dtd is not specified in the XML file, then the
735
// "debug" attribute is returned as the empty string.
736
if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {
737       LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
738     } else {
739       LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
740     }
741
742
743     String JavaDoc confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
744     if(!confDebug.equals("") && !confDebug.equals("null")) {
745       LogLog.warn("The \""+CONFIG_DEBUG_ATTR+"\" attribute is deprecated.");
746       LogLog.warn("Use the \""+INTERNAL_DEBUG_ATTR+"\" attribute instead.");
747       LogLog.setInternalDebugging(OptionConverter.toBoolean(confDebug, true));
748     }
749
750     String JavaDoc thresholdStr = subst(element.getAttribute(THRESHOLD_ATTR));
751     LogLog.debug("Threshold =\"" + thresholdStr +"\".");
752     if(!"".equals(thresholdStr) && !"null".equals(thresholdStr)) {
753       repository.setThreshold(thresholdStr);
754     }
755
756     //Hashtable appenderBag = new Hashtable(11);
757

758     /* Building Appender objects, placing them in a local namespace
759        for future reference */

760
761     // First configure each category factory under the root element.
762
// Category factories need to be configured before any of
763
// categories they support.
764
//
765
String JavaDoc tagName = null;
766     Element currentElement = null;
767     Node currentNode = null;
768     NodeList children = element.getChildNodes();
769     final int length = children.getLength();
770
771     for (int loop = 0; loop < length; loop++) {
772       currentNode = children.item(loop);
773       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
774     currentElement = (Element) currentNode;
775     tagName = currentElement.getTagName();
776
777     if (tagName.equals(CATEGORY_FACTORY_TAG)) {
778       parseCategoryFactory(currentElement);
779     }
780       }
781     }
782     
783     for (int loop = 0; loop < length; loop++) {
784       currentNode = children.item(loop);
785       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
786     currentElement = (Element) currentNode;
787     tagName = currentElement.getTagName();
788
789     if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
790       parseCategory(currentElement);
791     } else if (tagName.equals(ROOT_TAG)) {
792       parseRoot(currentElement);
793     } else if(tagName.equals(RENDERER_TAG)) {
794       parseRenderer(currentElement);
795     }
796       }
797     }
798   }
799
800   
801   protected
802   String JavaDoc subst(String JavaDoc value) {
803     try {
804       return OptionConverter.substVars(value, props);
805     } catch(IllegalArgumentException JavaDoc e) {
806       LogLog.warn("Could not perform variable substitution.", e);
807       return value;
808     }
809   }
810 }
811
812
813 class XMLWatchdog extends FileWatchdog {
814
815   XMLWatchdog(String JavaDoc filename) {
816     super(filename);
817   }
818
819   /**
820      Call {@link PropertyConfigurator#configure(String)} with the
821      <code>filename</code> to reconfigure log4j. */

822   public
823   void doOnChange() {
824     new DOMConfigurator().doConfigure(filename,
825                       LogManager.getLoggerRepository());
826   }
827 }
828
Popular Tags