📄 domconfigurator.java
字号:
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software
* License version 1.1, a copy of which has been included with this
* distribution in the LICENSE.txt file. */
package org.apache.log4j.xml;
import java.util.*;
import java.net.URL;
import org.w3c.dom.*;
import java.lang.reflect.Method;
import org.apache.log4j.*;
import org.apache.log4j.spi.*;
import org.apache.log4j.or.RendererMap;
import org.apache.log4j.helpers.*;
import org.apache.log4j.config.PropertySetter;
import org.xml.sax.InputSource;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.io.IOException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.FactoryConfigurationError;
// Contributors: Mark Womack
// Arun Katkere
/**
Use this class to initialize the log4j environment using a DOM tree.
<p>The DTD is specified in <a
href="doc-files/log4j.dtd"><b>log4j.dtd</b></a>.
<p>Sometimes it is useful to see how log4j is reading configuration
files. You can enable log4j internal logging by defining the
<b>log4j.debug</b> variable on the java command
line. Alternatively, set the <code>debug</code> attribute in the
<code>log4j:configuration</code> element. As in
<pre>
<log4j:configuration <b>debug="true"</b> xmlns:log4j="http://jakarta.apache.org/log4j/">
...
</log4j:configuration>
</pre>
<p>There are sample XML files included in the package.
@author Christopher Taylor
@author Ceki Gülcü
@author Anders Kristensen
@since 0.8.3 */
public class DOMConfigurator implements Configurator {
static final String CONFIGURATION_TAG = "log4j:configuration";
static final String OLD_CONFIGURATION_TAG = "configuration";
static final String RENDERER_TAG = "renderer";
static final String APPENDER_TAG = "appender";
static final String APPENDER_REF_TAG = "appender-ref";
static final String PARAM_TAG = "param";
static final String LAYOUT_TAG = "layout";
static final String CATEGORY = "category";
static final String LOGGER = "logger";
static final String LOGGER_REF = "logger-ref";
static final String CATEGORY_FACTORY_TAG = "categoryFactory";
static final String NAME_ATTR = "name";
static final String CLASS_ATTR = "class";
static final String VALUE_ATTR = "value";
static final String ROOT_TAG = "root";
static final String ROOT_REF = "root-ref";
static final String LEVEL_TAG = "level";
static final String PRIORITY_TAG = "priority";
static final String FILTER_TAG = "filter";
static final String ERROR_HANDLER_TAG = "errorHandler";
static final String REF_ATTR = "ref";
static final String ADDITIVITY_ATTR = "additivity";
static final String THRESHOLD_ATTR = "threshold";
static final String CONFIG_DEBUG_ATTR = "configDebug";
static final String INTERNAL_DEBUG_ATTR = "debug";
static final String RENDERING_CLASS_ATTR = "renderingClass";
static final String RENDERED_CLASS_ATTR = "renderedClass";
static final String EMPTY_STR = "";
static final Class[] ONE_STRING_PARAM = new Class[] {String.class};
final static String dbfKey = "javax.xml.parsers.DocumentBuilderFactory";
// key: appenderName, value: appender
Hashtable appenderBag;
Properties props;
LoggerRepository repository;
/**
No argument constructor.
*/
public
DOMConfigurator () {
appenderBag = new Hashtable();
}
/**
Used internally to parse appenders by IDREF name.
*/
protected
Appender findAppenderByName(Document doc, String appenderName) {
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;
}
}
}
/**
Used internally to parse appenders by IDREF element.
*/
protected
Appender findAppenderByReference(Element appenderRef) {
String appenderName = subst(appenderRef.getAttribute(REF_ATTR));
Document doc = appenderRef.getOwnerDocument();
return findAppenderByName(doc, appenderName);
}
/**
Used internally to parse an appender element.
*/
protected
Appender parseAppender (Element appenderElement) {
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.");
}
}
}
}
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;
}
}
/**
Used internally to parse an {@link ErrorHandler} element.
*/
protected
void parseErrorHandler(Element element, Appender appender) {
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 = repository.getLogger(loggerName);
eh.setLogger(logger);
} else if(tagName.equals(ROOT_REF)) {
Logger root = repository.getRootLogger();
eh.setLogger(root);
}
}
}
propSetter.activate();
appender.setErrorHandler(eh);
}
}
/**
Used internally to parse a filter element.
*/
protected
void parseFilters(Element element, Appender appender) {
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);
}
}
}
propSetter.activate();
LogLog.debug("Adding filter of type ["+filter.getClass()
+"] to appender named ["+appender.getName()+"].");
appender.addFilter(filter);
}
}
/**
Used internally to parse an category element.
*/
protected
void parseCategory (Element loggerElement) {
// 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 = repository.getLogger(catName);
}
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);
}
}
/**
Used internally to parse the category factory element.
*/
protected
void parseCategoryFactory(Element factoryElement) {
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 catFactory = OptionConverter.instantiateByClassName(className,
LoggerFactory.class,
null);
PropertySetter propSetter = new PropertySetter(catFactory);
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);
}
}
}
}
}
/**
Used internally to parse the roor category element.
*/
protected
void parseRoot (Element rootElement) {
Logger root = repository.getRootLogger();
// category configuration needs to be atomic
synchronized(root) {
parseChildrenOfLoggerElement(rootElement, root, true);
}
}
/**
Used internally to parse the children of a category element.
*/
protected
void parseChildrenOfLoggerElement(Element catElement,
Logger cat, boolean isRoot) {
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -