+++ /dev/null
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.log4j.xml;
-
-import org.apache.log4j.Appender;
-import org.apache.log4j.Layout;
-import org.apache.log4j.Level;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Logger;
-import org.apache.log4j.config.PropertySetter;
-import org.apache.log4j.helpers.FileWatchdog;
-import org.apache.log4j.helpers.Loader;
-import org.apache.log4j.helpers.LogLog;
-import org.apache.log4j.helpers.OptionConverter;
-import org.apache.log4j.or.RendererMap;
-import org.apache.log4j.spi.AppenderAttachable;
-import org.apache.log4j.spi.Configurator;
-import org.apache.log4j.spi.ErrorHandler;
-import org.apache.log4j.spi.Filter;
-import org.apache.log4j.spi.LoggerFactory;
-import org.apache.log4j.spi.LoggerRepository;
-import org.apache.log4j.spi.RendererSupport;
-import org.apache.log4j.spi.ThrowableRenderer;
-import org.apache.log4j.spi.ThrowableRendererSupport;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.FactoryConfigurationError;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.Reader;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Hashtable;
-import java.util.Properties;
-
-// 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";
- private static final String THROWABLE_RENDERER_TAG = "throwableRenderer";
- 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 LOGGER_FACTORY_TAG = "loggerFactory";
- 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";
- private static final String RESET_ATTR = "reset";
- 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;
-
- protected LoggerFactory catFactory = null;
-
- /**
- 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);
- if (appender != null) {
- 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);
- }
-
- /**
- * 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.
- */
- private static void parseUnrecognizedElement(final Object instance,
- final Element element,
- final Properties props) throws Exception {
- boolean recognized = false;
- if (instance instanceof UnrecognizedElementHandler) {
- recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
- element, props);
- }
- if (!recognized) {
- LogLog.warn("Unrecognized element " + element.getNodeName());
- }
- }
-
- /**
- * 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
- */
- private static void quietParseUnrecognizedElement(final Object instance,
- final Element element,
- final Properties props) {
- try {
- parseUnrecognizedElement(instance, element, props);
- } catch (Exception ex) {
- if (ex instanceof InterruptedException || ex instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- LogLog.error("Error in extension content: ", ex);
- }
- }
-
- /**
- 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.");
- }
- } 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) {
- if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- 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 = (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);
- }
- }
-
- /**
- 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);
- } else {
- quietParseUnrecognizedElement(filter, currentElement, props);
- }
- }
- }
- 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 = (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 (InvocationTargetException oops) {
- if (oops.getTargetException() instanceof InterruptedException
- || oops.getTargetException() instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- LogLog.error("Could not retrieve category ["+catName+
- "]. Reported error follows.", oops);
- return;
- } 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 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);
- }
- }
- }
- }
- }
-
-
- /**
- 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;
- 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();
- }
-
- /**
- Used internally to parse a layout element.
- */
- protected
- Layout parseLayout (Element 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 = 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) {
- if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- LogLog.error("Could not create the Layout. Reported error follows.",
- oops);
- return null;
- }
- }
-
- protected
- void parseRenderer(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);
- }
- }
-
- /**
- * Parses throwable renderer.
- * @param element throwableRenderer element.
- * @return configured throwable renderer.
- * @since 1.2.16.
- */
- protected ThrowableRenderer parseThrowableRenderer(final Element element) {
- String className = subst(element.getAttribute(CLASS_ATTR));
- LogLog.debug("Parsing throwableRenderer of class: \""+className+"\"");
- try {
- Object instance = Loader.loadClass(className).newInstance();
- ThrowableRenderer tr = (ThrowableRenderer)instance;
- PropertySetter propSetter = new PropertySetter(tr);
-
- NodeList params = element.getChildNodes();
- final int length = params.getLength();
-
- for (int loop = 0; loop < length; loop++) {
- Node currentNode = 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 tr;
- }
- catch (Exception oops) {
- if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- LogLog.error("Could not create the ThrowableRenderer. Reported error follows.",
- oops);
- return null;
- }
- }
-
- /**
- Used internally to parse a level element.
- */
- protected
- void parseLevel(Element element, Logger logger, boolean isRoot) {
- 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) {
- if (oops instanceof InterruptedException || oops instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- LogLog.error("Could not create level ["+priStr+
- "]. Reported error follows.", oops);
- return;
- }
- }
- }
- LogLog.debug(catName + " level set to " + logger.getLevel());
- }
-
- protected
- void setParameter(Element elem, PropertySetter propSetter) {
- String name = subst(elem.getAttribute(NAME_ATTR));
- String value = (elem.getAttribute(VALUE_ATTR));
- value = subst(OptionConverter.convertSpecialChars(value));
- propSetter.setProperty(name, value);
- }
-
-
- /**
- Configure log4j using a <code>configuration</code> element as
- defined in the log4j.dtd.
-
- */
- static
- public
- void configure (Element element) {
- DOMConfigurator configurator = new DOMConfigurator();
- configurator.doConfigure(element, LogManager.getLoggerRepository());
- }
-
- /**
- 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.
-
- */
- static
- public
- void configureAndWatch(String configFilename) {
- configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
- }
-
- /**
- Read the configuration file <code>configFilename</code> if it
- exists. Moreover, a thread will be created that will periodically
- check if <code>configFilename</code> has been created or
- modified. The period is determined by the <code>delay</code>
- argument. If a change or file creation is detected, then
- <code>configFilename</code> 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.
- */
- static
- public
- void configureAndWatch(String configFilename, long delay) {
- XMLWatchdog xdog = new XMLWatchdog(configFilename);
- xdog.setDelay(delay);
- xdog.start();
- }
-
- private interface ParseAction {
- Document parse(final DocumentBuilder parser) throws SAXException, IOException;
- }
-
-
- public
- void doConfigure(final String filename, 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
- void doConfigure(final URL url, LoggerRepository repository) {
- ParseAction action = new ParseAction() {
- public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
- URLConnection uConn = url.openConnection();
- uConn.setUseCaches(false);
- InputStream stream = uConn.getInputStream();
- try {
- InputSource src = new InputSource(stream);
- src.setSystemId(url.toString());
- return parser.parse(src);
- } finally {
- stream.close();
- }
- }
- public String toString() {
- return "url [" + url.toString() + "]";
- }
- };
- doConfigure(action, repository);
- }
-
- /**
- Configure log4j by reading in a log4j.dtd compliant XML
- configuration file.
-
- */
- public
- void doConfigure(final InputStream inputStream, LoggerRepository repository)
- throws FactoryConfigurationError {
- 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);
- }
-
- /**
- Configure log4j by reading in a log4j.dtd compliant XML
- configuration file.
-
- */
- public
- void doConfigure(final Reader reader, LoggerRepository repository)
- throws FactoryConfigurationError {
- 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);
- }
-
- /**
- Configure log4j by reading in a log4j.dtd compliant XML
- configuration file.
-
- */
- protected
- void doConfigure(final InputSource inputSource, LoggerRepository repository)
- throws FactoryConfigurationError {
- 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 void doConfigure(final ParseAction action, final LoggerRepository repository)
- throws FactoryConfigurationError {
- 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) {
- if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
- Thread.currentThread().interrupt();
- }
- // I know this is miserable...
- LogLog.error("Could not parse "+ action.toString() + ".", e);
- }
- }
-
- /**
- Configure by taking in an DOM element.
- */
- public void doConfigure(Element element, LoggerRepository repository) {
- this.repository = repository;
- parse(element);
- }
-
-
- /**
- A static version of {@link #doConfigure(String, LoggerRepository)}. */
- static
- public
- void configure(String filename) throws FactoryConfigurationError {
- new DOMConfigurator().doConfigure(filename,
- LogManager.getLoggerRepository());
- }
-
- /**
- A static version of {@link #doConfigure(URL, LoggerRepository)}.
- */
- static
- public
- void configure(URL url) throws FactoryConfigurationError {
- new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
- }
-
- /**
- Used internally to configure the log4j framework by parsing a DOM
- tree of XML elements based on <a
- href="doc-files/log4j.dtd">log4j.dtd</a>.
-
- */
- protected
- void parse(Element element) {
-
- 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(THROWABLE_RENDERER_TAG)) {
- if (repository instanceof ThrowableRendererSupport) {
- ThrowableRenderer tr = parseThrowableRenderer(currentElement);
- if (tr != null) {
- ((ThrowableRendererSupport) repository).setThrowableRenderer(tr);
- }
- }
- } else if (!(tagName.equals(APPENDER_TAG)
- || tagName.equals(CATEGORY_FACTORY_TAG)
- || tagName.equals(LOGGER_FACTORY_TAG))) {
- quietParseUnrecognizedElement(repository, currentElement, props);
- }
- }
- }
- }
-
-
- protected
- String subst(final String value) {
- return subst(value, 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
- */
- public static String subst(final String value, final Properties props) {
- try {
- return OptionConverter.substVars(value, props);
- } catch (IllegalArgumentException e) {
- LogLog.warn("Could not perform variable substitution.", e);
- return value;
- }
- }
-
-
- /**
- * 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
- */
- public static void setParameter(final Element elem,
- final PropertySetter propSetter,
- final Properties props) {
- String name = subst(elem.getAttribute("name"), props);
- String value = (elem.getAttribute("value"));
- value = subst(OptionConverter.convertSpecialChars(value), props);
- propSetter.setProperty(name, value);
- }
-
- /**
- * 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
- */
- public static Object parseElement(final Element element,
- final Properties props,
- final Class expectedClass) throws Exception {
- 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;
- }
-
-}
-
-
-class XMLWatchdog extends FileWatchdog {
-
- XMLWatchdog(String filename) {
- super(filename);
- }
-
- /**
- Call {@link DOMConfigurator#configure(String)} with the
- <code>filename</code> to reconfigure log4j. */
- public
- void doOnChange() {
- new DOMConfigurator().doConfigure(filename,
- LogManager.getLoggerRepository());
- }
-}