FileDocCategorySizeDatePackage
DOMConfigurator.javaAPI DocApache log4j 1.2.1535640Sat Aug 25 00:09:42 BST 2007org.apache.log4j.xml

DOMConfigurator

public class DOMConfigurator extends Object implements Configurator
Use this class to initialize the log4j environment using a DOM tree.

The DTD is specified in log4j.dtd.

Sometimes it is useful to see how log4j is reading configuration files. You can enable log4j internal logging by defining the log4j.debug variable on the java command line. Alternatively, set the debug attribute in the log4j:configuration element. As in

<log4j:configuration debug="true" xmlns:log4j="http://jakarta.apache.org/log4j/">
...
</log4j:configuration>

There are sample XML files included in the package.

author
Christopher Taylor
author
Ceki Gülcü
author
Anders Kristensen
since
0.8.3

Fields Summary
static final String
CONFIGURATION_TAG
static final String
OLD_CONFIGURATION_TAG
static final String
RENDERER_TAG
static final String
APPENDER_TAG
static final String
APPENDER_REF_TAG
static final String
PARAM_TAG
static final String
LAYOUT_TAG
static final String
CATEGORY
static final String
LOGGER
static final String
LOGGER_REF
static final String
CATEGORY_FACTORY_TAG
static final String
LOGGER_FACTORY_TAG
static final String
NAME_ATTR
static final String
CLASS_ATTR
static final String
VALUE_ATTR
static final String
ROOT_TAG
static final String
ROOT_REF
static final String
LEVEL_TAG
static final String
PRIORITY_TAG
static final String
FILTER_TAG
static final String
ERROR_HANDLER_TAG
static final String
REF_ATTR
static final String
ADDITIVITY_ATTR
static final String
THRESHOLD_ATTR
static final String
CONFIG_DEBUG_ATTR
static final String
INTERNAL_DEBUG_ATTR
private static final String
RESET_ATTR
static final String
RENDERING_CLASS_ATTR
static final String
RENDERED_CLASS_ATTR
static final String
EMPTY_STR
static final Class[]
ONE_STRING_PARAM
static final String
dbfKey
Hashtable
appenderBag
Properties
props
LoggerRepository
repository
protected LoggerFactory
catFactory
Constructors Summary
public DOMConfigurator()
No argument constructor.


           
  
     
    appenderBag = new Hashtable();
  
Methods Summary
public static voidconfigure(org.w3c.dom.Element element)
Configure log4j using a configuration element as defined in the log4j.dtd.

    DOMConfigurator configurator = new DOMConfigurator();
    configurator.doConfigure(element,  LogManager.getLoggerRepository());
  
public static voidconfigure(java.lang.String filename)
A static version of {@link #doConfigure(String, LoggerRepository)}.

    new DOMConfigurator().doConfigure(filename, 
				      LogManager.getLoggerRepository());
  
public static voidconfigure(java.net.URL url)
A static version of {@link #doConfigure(URL, LoggerRepository)}.

    new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
  
public static voidconfigureAndWatch(java.lang.String configFilename)
Like {@link #configureAndWatch(String, long)} except that the default delay as defined by {@link FileWatchdog#DEFAULT_DELAY} is used.

param
configFilename A log4j configuration file in XML format.

    configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
  
public static voidconfigureAndWatch(java.lang.String configFilename, long delay)
Read the configuration file configFilename if it exists. Moreover, a thread will be created that will periodically check if configFilename has been created or modified. The period is determined by the delay argument. If a change or file creation is detected, then configFilename is read to configure log4j.

param
configFilename A log4j configuration file in XML format.
param
delay The delay in milliseconds to wait between each check.

    XMLWatchdog xdog = new XMLWatchdog(configFilename);
    xdog.setDelay(delay);
    xdog.start();
  
public voiddoConfigure(java.lang.String filename, org.apache.log4j.spi.LoggerRepository repository)

    ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              return parser.parse(new File(filename));
          }
          public String toString() { 
              return "file [" + filename + "]"; 
          }
    };
    doConfigure(action, repository);
  
public voiddoConfigure(java.net.URL url, org.apache.log4j.spi.LoggerRepository repository)

      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              return parser.parse(url.toString());
          }
          public String toString() { 
              return "url [" + url.toString() + "]"; 
          }
      };
      doConfigure(action, repository);
  
public voiddoConfigure(java.io.InputStream inputStream, org.apache.log4j.spi.LoggerRepository repository)
Configure log4j by reading in a log4j.dtd compliant XML configuration file.

      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              InputSource inputSource = new InputSource(inputStream);
              inputSource.setSystemId("dummy://log4j.dtd");
              return parser.parse(inputSource);
          }
          public String toString() { 
              return "input stream [" + inputStream.toString() + "]"; 
          }
      };
      doConfigure(action, repository);
  
public voiddoConfigure(java.io.Reader reader, org.apache.log4j.spi.LoggerRepository repository)
Configure log4j by reading in a log4j.dtd compliant XML configuration file.

      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              InputSource inputSource = new InputSource(reader);
              inputSource.setSystemId("dummy://log4j.dtd");
              return parser.parse(inputSource);
          }
          public String toString() { 
              return "reader [" + reader.toString() + "]"; 
          }
      };
    doConfigure(action, repository);
  
protected voiddoConfigure(org.xml.sax.InputSource inputSource, org.apache.log4j.spi.LoggerRepository repository)
Configure log4j by reading in a log4j.dtd compliant XML configuration file.

      if (inputSource.getSystemId() == null) {
          inputSource.setSystemId("dummy://log4j.dtd");
      }
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              return parser.parse(inputSource);
          }
          public String toString() { 
              return "input source [" + inputSource.toString() + "]"; 
          }
      };
      doConfigure(action, repository);
    
private final voiddoConfigure(org.apache.log4j.xml.DOMConfigurator$ParseAction action, org.apache.log4j.spi.LoggerRepository repository)

    DocumentBuilderFactory dbf = null;
    this.repository = repository;
    try { 
      LogLog.debug("System property is :"+
  	                        OptionConverter.getSystemProperty(dbfKey, 
								  null)); 
      dbf = DocumentBuilderFactory.newInstance();
      LogLog.debug("Standard DocumentBuilderFactory search succeded.");
      LogLog.debug("DocumentBuilderFactory is: "+dbf.getClass().getName());
    } catch(FactoryConfigurationError fce) {
      Exception e = fce.getException();
      LogLog.debug("Could not instantiate a DocumentBuilderFactory.", e);
      throw fce;
    }
      
    try {
      dbf.setValidating(true);

      DocumentBuilder docBuilder = dbf.newDocumentBuilder();

      docBuilder.setErrorHandler(new SAXErrorHandler());      
      docBuilder.setEntityResolver(new Log4jEntityResolver());
         
      Document doc = action.parse(docBuilder);     
      parse(doc.getDocumentElement());
    } catch (Exception e) {
      // I know this is miserable...
      LogLog.error("Could not parse "+ action.toString() + ".", e);
    }
  
public voiddoConfigure(org.w3c.dom.Element element, org.apache.log4j.spi.LoggerRepository repository)
Configure by taking in an DOM element.

    this.repository = repository;
    parse(element);
  
protected org.apache.log4j.AppenderfindAppenderByName(org.w3c.dom.Document doc, java.lang.String appenderName)
Used internally to parse appenders by IDREF name.

      
    Appender appender = (Appender) appenderBag.get(appenderName);

    if(appender != null) {
      return appender;
    } else {
      // Doesn't work on DOM Level 1 :
      // Element element = doc.getElementById(appenderName);
                        
      // Endre's hack:
      Element element = null;
      NodeList list = doc.getElementsByTagName("appender");
      for (int t=0; t < list.getLength(); t++) {
	Node node = list.item(t);
	NamedNodeMap map= node.getAttributes();
	Node attrNode = map.getNamedItem("name");
	if (appenderName.equals(attrNode.getNodeValue())) {
	  element = (Element) node;
	  break;
	}
      }
      // Hack finished.

      if(element == null) {
	LogLog.error("No appender named ["+appenderName+"] could be found."); 
	return null;
      } else {
	appender = parseAppender(element);
	appenderBag.put(appenderName, appender);
	return appender;
      }
    } 
  
protected org.apache.log4j.AppenderfindAppenderByReference(org.w3c.dom.Element appenderRef)
Used internally to parse appenders by IDREF element.

    
    String appenderName = subst(appenderRef.getAttribute(REF_ATTR));    
    Document doc = appenderRef.getOwnerDocument();
    return findAppenderByName(doc, appenderName);
  
protected voidparse(org.w3c.dom.Element element)
Used internally to configure the log4j framework by parsing a DOM tree of XML elements based on log4j.dtd.


    String rootElementName = element.getTagName();

    if (!rootElementName.equals(CONFIGURATION_TAG)) {
      if(rootElementName.equals(OLD_CONFIGURATION_TAG)) {
	LogLog.warn("The <"+OLD_CONFIGURATION_TAG+
		     "> element has been deprecated.");
	LogLog.warn("Use the <"+CONFIGURATION_TAG+"> element instead.");
      } else {
	LogLog.error("DOM element is - not a <"+CONFIGURATION_TAG+"> element.");
	return;
      }
    }


    String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));
      
    LogLog.debug("debug attribute= \"" + debugAttrib +"\".");
    // if the log4j.dtd is not specified in the XML file, then the
    // "debug" attribute is returned as the empty string.
    if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {      
      LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
    } else {
      LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
    }

      //
      //   reset repository before configuration if reset="true"
      //       on configuration element.
      //
    String resetAttrib = subst(element.getAttribute(RESET_ATTR));
    LogLog.debug("reset attribute= \"" + resetAttrib +"\".");
    if(!("".equals(resetAttrib))) {
         if (OptionConverter.toBoolean(resetAttrib, false)) {
             repository.resetConfiguration();
         }
    }



    String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
    if(!confDebug.equals("") && !confDebug.equals("null")) {      
      LogLog.warn("The \""+CONFIG_DEBUG_ATTR+"\" attribute is deprecated.");
      LogLog.warn("Use the \""+INTERNAL_DEBUG_ATTR+"\" attribute instead.");
      LogLog.setInternalDebugging(OptionConverter.toBoolean(confDebug, true));
    }

    String thresholdStr = subst(element.getAttribute(THRESHOLD_ATTR));
    LogLog.debug("Threshold =\"" + thresholdStr +"\".");
    if(!"".equals(thresholdStr) && !"null".equals(thresholdStr)) {
      repository.setThreshold(thresholdStr);
    }

    //Hashtable appenderBag = new Hashtable(11);

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

    // First configure each category factory under the root element.
    // Category factories need to be configured before any of
    // categories they support.
    //
    String   tagName = null;
    Element  currentElement = null;
    Node     currentNode = null;
    NodeList children = element.getChildNodes();
    final int length = children.getLength();

    for (int loop = 0; loop < length; loop++) {
      currentNode = children.item(loop);
      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	currentElement = (Element) currentNode;
	tagName = currentElement.getTagName();

	if (tagName.equals(CATEGORY_FACTORY_TAG) || tagName.equals(LOGGER_FACTORY_TAG)) {
	  parseCategoryFactory(currentElement);
	}
      }
    }
    
    for (int loop = 0; loop < length; loop++) {
      currentNode = children.item(loop);
      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	currentElement = (Element) currentNode;
	tagName = currentElement.getTagName();

	if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
	  parseCategory(currentElement);
	} else if (tagName.equals(ROOT_TAG)) {
	  parseRoot(currentElement);
	} else if(tagName.equals(RENDERER_TAG)) {
	  parseRenderer(currentElement);
	} else if (!(tagName.equals(APPENDER_TAG)
            || tagName.equals(CATEGORY_FACTORY_TAG)
            || tagName.equals(LOGGER_FACTORY_TAG))) {
        quietParseUnrecognizedElement(repository, currentElement, props);
    }
      }
    }
  
protected org.apache.log4j.AppenderparseAppender(org.w3c.dom.Element appenderElement)
Used internally to parse an appender element.

    String className = subst(appenderElement.getAttribute(CLASS_ATTR));
    LogLog.debug("Class name: [" + className+']");    
    try {
      Object instance 	= Loader.loadClass(className).newInstance();
      Appender appender	= (Appender)instance;
      PropertySetter propSetter = new PropertySetter(appender);

      appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));
      
      NodeList children	= appenderElement.getChildNodes();
      final int length 	= children.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = children.item(loop);

	/* We're only interested in Elements */
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element)currentNode;

	  // Parse appender parameters 
	  if (currentElement.getTagName().equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  }
	  // Set appender layout
	  else if (currentElement.getTagName().equals(LAYOUT_TAG)) {
	    appender.setLayout(parseLayout(currentElement));
	  }
	  // Add filters
	  else if (currentElement.getTagName().equals(FILTER_TAG)) {
	    parseFilters(currentElement, appender);
	  }
	  else if (currentElement.getTagName().equals(ERROR_HANDLER_TAG)) {
	    parseErrorHandler(currentElement, appender);
	  }
	  else if (currentElement.getTagName().equals(APPENDER_REF_TAG)) {
	    String refName = subst(currentElement.getAttribute(REF_ATTR));
	    if(appender instanceof AppenderAttachable) {
	      AppenderAttachable aa = (AppenderAttachable) appender;
	      LogLog.debug("Attaching appender named ["+ refName+
			   "] to appender named ["+ appender.getName()+"].");
	      aa.addAppender(findAppenderByReference(currentElement));
	    } else {
	      LogLog.error("Requesting attachment of appender named ["+
			   refName+ "] to appender named ["+ appender.getName()+
                "] which does not implement org.apache.log4j.spi.AppenderAttachable.");
	    }
	  } else {
          parseUnrecognizedElement(instance, currentElement, props);
      }
	}
      }
      propSetter.activate();
      return appender;
    }
    /* Yes, it's ugly.  But all of these exceptions point to the same
       problem: we can't create an Appender */
    catch (Exception oops) {
      LogLog.error("Could not create an Appender. Reported error follows.",
		   oops);
      return null;
    }
  
protected voidparseCategory(org.w3c.dom.Element loggerElement)
Used internally to parse an category element.

    // Create a new org.apache.log4j.Category object from the <category> element.
    String catName = subst(loggerElement.getAttribute(NAME_ATTR));

    Logger cat;    

    String className = subst(loggerElement.getAttribute(CLASS_ATTR));


    if(EMPTY_STR.equals(className)) {
      LogLog.debug("Retreiving an instance of org.apache.log4j.Logger.");
      cat = (catFactory == null) ? repository.getLogger(catName) : repository.getLogger(catName, catFactory);
    }
    else {
      LogLog.debug("Desired logger sub-class: ["+className+']");
       try {	 
	 Class clazz = Loader.loadClass(className);
	 Method getInstanceMethod = clazz.getMethod("getLogger", 
						    ONE_STRING_PARAM);
	 cat = (Logger) getInstanceMethod.invoke(null, new Object[] {catName});
       } catch (Exception oops) {
	 LogLog.error("Could not retrieve category ["+catName+
		      "]. Reported error follows.", oops);
	 return;
       }
    }

    // Setting up a category needs to be an atomic operation, in order
    // to protect potential log operations while category
    // configuration is in progress.
    synchronized(cat) {
      boolean additivity = OptionConverter.toBoolean(
                           subst(loggerElement.getAttribute(ADDITIVITY_ATTR)),
			   true);
    
      LogLog.debug("Setting ["+cat.getName()+"] additivity to ["+additivity+"].");
      cat.setAdditivity(additivity);
      parseChildrenOfLoggerElement(loggerElement, cat, false);
    }
  
protected voidparseCategoryFactory(org.w3c.dom.Element factoryElement)
Used internally to parse the category factory element.

    String className = subst(factoryElement.getAttribute(CLASS_ATTR));

    if(EMPTY_STR.equals(className)) {
      LogLog.error("Category Factory tag " + CLASS_ATTR + " attribute not found.");
      LogLog.debug("No Category Factory configured.");
    }
    else {
      LogLog.debug("Desired category factory: ["+className+']");
      Object factory = OptionConverter.instantiateByClassName(className,
                                                                 LoggerFactory.class, 
                                                                 null);
      if (factory instanceof LoggerFactory) {
          catFactory = (LoggerFactory) factory;
      } else {
          LogLog.error("Category Factory class " + className + " does not implement org.apache.log4j.LoggerFactory");
      }
      PropertySetter propSetter = new PropertySetter(factory);

      Element  currentElement = null;
      Node     currentNode    = null;
      NodeList children       = factoryElement.getChildNodes();
      final int length        = children.getLength();

      for (int loop=0; loop < length; loop++) {
        currentNode = children.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  currentElement = (Element)currentNode;
	  if (currentElement.getTagName().equals(PARAM_TAG)) {
	    setParameter(currentElement, propSetter);
	  } else {
           quietParseUnrecognizedElement(factory, currentElement, props);
      }
	}
      }
    }
  
protected voidparseChildrenOfLoggerElement(org.w3c.dom.Element catElement, org.apache.log4j.Logger cat, boolean isRoot)
Used internally to parse the children of a category element.

    
    PropertySetter propSetter = new PropertySetter(cat);
    
    // Remove all existing appenders from cat. They will be
    // reconstructed if need be.
    cat.removeAllAppenders();


    NodeList children 	= catElement.getChildNodes();
    final int length 	= children.getLength();
    
    for (int loop = 0; loop < length; loop++) {
      Node currentNode = children.item(loop);

      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	Element currentElement = (Element) currentNode;
	String tagName = currentElement.getTagName();
	
	if (tagName.equals(APPENDER_REF_TAG)) {
	  Element appenderRef = (Element) currentNode;
	  Appender appender = findAppenderByReference(appenderRef);
	  String refName =  subst(appenderRef.getAttribute(REF_ATTR));
	  if(appender != null)
	    LogLog.debug("Adding appender named ["+ refName+ 
			 "] to category ["+cat.getName()+"].");
	  else 
	    LogLog.debug("Appender named ["+ refName + "] not found.");
	    
	  cat.addAppender(appender);
	  
	} else if(tagName.equals(LEVEL_TAG)) {
	  parseLevel(currentElement, cat, isRoot);	
	} else if(tagName.equals(PRIORITY_TAG)) {
	  parseLevel(currentElement, cat, isRoot);
	} else if(tagName.equals(PARAM_TAG)) {
          setParameter(currentElement, propSetter);
	} else {
        quietParseUnrecognizedElement(cat, currentElement, props);
    }
      }
    }
    propSetter.activate();
  
public static java.lang.ObjectparseElement(org.w3c.dom.Element element, java.util.Properties props, java.lang.Class expectedClass)
Creates an object and processes any nested param elements but does not call activateOptions. If the class also supports UnrecognizedElementParser, the parseUnrecognizedElement method will be call for any child elements other than param.

param
element element, may not be null.
param
props properties
param
expectedClass interface or class expected to be implemented by created class
return
created class or null.
throws
Exception thrown if the contain object should be abandoned.
since
1.2.15

        String clazz = subst(element.getAttribute("class"), props);
        Object instance = OptionConverter.instantiateByClassName(clazz,
                expectedClass, null);

        if (instance != null) {
            PropertySetter propSetter = new PropertySetter(instance);
            NodeList children = element.getChildNodes();
            final int length = children.getLength();

            for (int loop = 0; loop < length; loop++) {
                Node currentNode = children.item(loop);
                if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element currentElement = (Element) currentNode;
                    String tagName = currentElement.getTagName();
                    if (tagName.equals("param")) {
                        setParameter(currentElement, propSetter, props);
                    } else {
                         parseUnrecognizedElement(instance, currentElement, props);
                    }
                }
            }
            return instance;
        }
        return null;
    
protected voidparseErrorHandler(org.w3c.dom.Element element, org.apache.log4j.Appender appender)
Used internally to parse an {@link ErrorHandler} element.

    ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
                                       subst(element.getAttribute(CLASS_ATTR)),
                                       org.apache.log4j.spi.ErrorHandler.class, 
 				       null);
    
    if(eh != null) {
      eh.setAppender(appender);

      PropertySetter propSetter = new PropertySetter(eh);
      NodeList children = element.getChildNodes();
      final int length 	= children.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = children.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element) currentNode;
	  String tagName = currentElement.getTagName();
	  if(tagName.equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  } else if(tagName.equals(APPENDER_REF_TAG)) {
	    eh.setBackupAppender(findAppenderByReference(currentElement));
	  } else if(tagName.equals(LOGGER_REF)) {
	    String loggerName = currentElement.getAttribute(REF_ATTR);	    
	    Logger logger = (catFactory == null) ? repository.getLogger(loggerName)
                : repository.getLogger(loggerName, catFactory);
	    eh.setLogger(logger);
	  } else if(tagName.equals(ROOT_REF)) {
	    Logger root = repository.getRootLogger();
	    eh.setLogger(root);
	  } else {
          quietParseUnrecognizedElement(eh, currentElement, props);
      }
	}
      }
      propSetter.activate();
      appender.setErrorHandler(eh);
    }
  
protected voidparseFilters(org.w3c.dom.Element element, org.apache.log4j.Appender appender)
Used internally to parse a filter element.

    String clazz = subst(element.getAttribute(CLASS_ATTR));
    Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz,
                                                Filter.class, null);
    
    if(filter != null) {
      PropertySetter propSetter = new PropertySetter(filter);
      NodeList children = element.getChildNodes();
      final int length 	= children.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = children.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element) currentNode;
	  String tagName = currentElement.getTagName();
	  if(tagName.equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  } else {
            quietParseUnrecognizedElement(filter, currentElement, props);
      }
	}
      }
      propSetter.activate();
      LogLog.debug("Adding filter of type ["+filter.getClass()
		   +"] to appender named ["+appender.getName()+"].");
      appender.addFilter(filter);
    }    
  
protected org.apache.log4j.LayoutparseLayout(org.w3c.dom.Element layout_element)
Used internally to parse a layout element.

    String className = subst(layout_element.getAttribute(CLASS_ATTR));
    LogLog.debug("Parsing layout of class: \""+className+"\"");		 
    try {
      Object instance 	= Loader.loadClass(className).newInstance();
      Layout layout   	= (Layout)instance;
      PropertySetter propSetter = new PropertySetter(layout);
      
      NodeList params 	= layout_element.getChildNodes();
      final int length 	= params.getLength();

      for (int loop = 0; loop < length; loop++) {
	Node currentNode = (Node)params.item(loop);
	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	  Element currentElement = (Element) currentNode;
	  String tagName = currentElement.getTagName();
	  if(tagName.equals(PARAM_TAG)) {
            setParameter(currentElement, propSetter);
	  } else {
          parseUnrecognizedElement(instance, currentElement, props);
      }
	}
      }
      
      propSetter.activate();
      return layout;
    }
    catch (Exception oops) {
      LogLog.error("Could not create the Layout. Reported error follows.",
		   oops);
      return null;
    }
  
protected voidparseLevel(org.w3c.dom.Element element, org.apache.log4j.Logger logger, boolean isRoot)
Used internally to parse a level element.

    String catName = logger.getName();
    if(isRoot) {
      catName = "root";
    }

    String priStr = subst(element.getAttribute(VALUE_ATTR));
    LogLog.debug("Level value for "+catName+" is  ["+priStr+"].");
    
    if(INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
      if(isRoot) {
	LogLog.error("Root level cannot be inherited. Ignoring directive.");
      } else {
	logger.setLevel(null);
      }
    } else {
      String className = subst(element.getAttribute(CLASS_ATTR));      
      if(EMPTY_STR.equals(className)) {	
	logger.setLevel(OptionConverter.toLevel(priStr, Level.DEBUG));
      } else {
	LogLog.debug("Desired Level sub-class: ["+className+']");
	try {	 
	  Class clazz = Loader.loadClass(className);
	  Method toLevelMethod = clazz.getMethod("toLevel", 
						    ONE_STRING_PARAM);
	  Level pri = (Level) toLevelMethod.invoke(null, 
						    new Object[] {priStr});
	  logger.setLevel(pri);
	} catch (Exception oops) {
	  LogLog.error("Could not create level ["+priStr+
		       "]. Reported error follows.", oops);
	  return;
	}
      }
    }
    LogLog.debug(catName + " level set to " + logger.getLevel());    
  
protected voidparseRenderer(org.w3c.dom.Element element)

    String renderingClass = subst(element.getAttribute(RENDERING_CLASS_ATTR));
    String renderedClass = subst(element.getAttribute(RENDERED_CLASS_ATTR));
    if(repository instanceof RendererSupport) {
      RendererMap.addRenderer((RendererSupport) repository, renderedClass, 
			      renderingClass);
    }
  
protected voidparseRoot(org.w3c.dom.Element rootElement)
Used internally to parse the roor category element.

    Logger root = repository.getRootLogger();
    // category configuration needs to be atomic
    synchronized(root) {    
      parseChildrenOfLoggerElement(rootElement, root, true);
    }
  
private static voidparseUnrecognizedElement(java.lang.Object instance, org.w3c.dom.Element element, java.util.Properties props)
Delegates unrecognized content to created instance if it supports UnrecognizedElementParser.

since
1.2.15
param
instance instance, may be null.
param
element element, may not be null.
param
props properties
throws
IOException thrown if configuration of owner object should be abandoned.

      boolean recognized = false;
      if (instance instanceof UnrecognizedElementHandler) {
          recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
                  element, props);
      }
      if (!recognized) {
          LogLog.warn("Unrecognized element " + element.getNodeName());
      }
  
private static voidquietParseUnrecognizedElement(java.lang.Object instance, org.w3c.dom.Element element, java.util.Properties props)
Delegates unrecognized content to created instance if it supports UnrecognizedElementParser and catches and logs any exception.

since
1.2.15
param
instance instance, may be null.
param
element element, may not be null.
param
props properties

      try {
          parseUnrecognizedElement(instance, element, props);
      } catch (Exception ex) {
          LogLog.error("Error in extension content: ", ex);
      }
  
protected voidsetParameter(org.w3c.dom.Element elem, org.apache.log4j.config.PropertySetter propSetter)

      setParameter(elem, propSetter, props);
  
public static voidsetParameter(org.w3c.dom.Element elem, org.apache.log4j.config.PropertySetter propSetter, java.util.Properties props)
Sets a parameter based from configuration file content.

param
elem param element, may not be null.
param
propSetter property setter, may not be null.
param
props properties
since
1.2.15

        String name = subst(elem.getAttribute("name"), props);
        String value = (elem.getAttribute("value"));
        value = subst(OptionConverter.convertSpecialChars(value), props);
        propSetter.setProperty(name, value);
    
protected java.lang.Stringsubst(java.lang.String value)

      return subst(value, props);
  
public static java.lang.Stringsubst(java.lang.String value, java.util.Properties props)
Substitutes property value for any references in expression.

param
value value from configuration file, may contain literal text, property references or both
param
props properties.
return
evaluated expression, may still contain expressions if unable to expand.
since
1.2.15

        try {
            return OptionConverter.substVars(value, props);
        } catch (IllegalArgumentException e) {
            LogLog.warn("Could not perform variable substitution.", e);
            return value;
        }