blob: 202f753bfd39cdc9b08afb81528870f686ff6b0d [file] [log] [blame]
/*
* 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.LogManager;
import org.apache.log4j.config.PropertySetter;
import org.apache.log4j.helpers.FileWatchdog;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.plugins.Plugin;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.LoggerRepositoryEx;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.parsers.FactoryConfigurationError;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* This class extends DOMConfigurator to support
* processing of plugin elements.
*/
public class PluginConfigurator extends
org.apache.log4j.xml.DOMConfigurator {
/**
* Create new instance.
*/
public PluginConfigurator() {
super();
}
/**
Configure log4j using a <code>configuration</code> element as
defined in the log4j.dtd.
*/
static
public
void configure (final Element element) {
PluginConfigurator configurator = new PluginConfigurator();
configurator.doConfigure(element, LogManager.getLoggerRepository());
}
/**
A static version of {@link #doConfigure(String, LoggerRepository)}. */
static
public
void configure(final String filename) throws FactoryConfigurationError {
new PluginConfigurator().doConfigure(filename,
LogManager.getLoggerRepository());
}
/**
A static version of {@link #doConfigure(URL, LoggerRepository)}.
*/
static
public
void configure(final URL url) throws FactoryConfigurationError {
new PluginConfigurator().doConfigure(url, LogManager.getLoggerRepository());
}
/**
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(final String configFilename, final long delay) {
PluginWatchdog xdog = new PluginWatchdog(configFilename);
xdog.setDelay(delay);
xdog.start();
}
/**
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(final String configFilename) {
configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
}
/**
* {@inheritDoc}
*/
protected void parse(final Element element) {
super.parse(element);
if (repository instanceof LoggerRepositoryEx) {
List plugins = new ArrayList();
createPlugins((LoggerRepositoryEx) repository, plugins, element);
for (Iterator iter = plugins.iterator(); iter.hasNext();) {
((Plugin) iter.next()).activateOptions();
}
}
}
/**
* Iterates over child nodes looking for plugin elements
* and constructs the plugins.
* @param repox repository
* @param plugins list to receive created plugins
* @param node parent node
*/
private void createPlugins(
final LoggerRepositoryEx repox,
final List plugins, final Node node) {
Node child = node.getFirstChild();
while (child != null) {
switch (child.getNodeType()) {
case Node.ELEMENT_NODE:
if ("plugin".equals(child.getNodeName())) {
createPlugin(repox, plugins, (Element) child);
}
break;
case Node.ENTITY_REFERENCE_NODE:
createPlugins(repox, plugins, child);
break;
default:
}
child = child.getNextSibling();
}
}
/**
* Iterates over children of plugin node looking for
* param elements.
* @param propSetter property setter
* @param parent parent node
*/
private void setParams(final PropertySetter propSetter,
final Node parent) {
Node child = parent.getFirstChild();
while (child != null) {
switch (child.getNodeType()) {
case Node.ELEMENT_NODE:
if ("param".equals(child.getNodeName())) {
setParameter((Element) child, propSetter);
}
break;
case Node.ENTITY_REFERENCE_NODE:
setParams(propSetter, child);
break;
default:
}
child = child.getNextSibling();
}
}
/**
* Creates a plugin
* @param repox repository
* @param plugins list of receive created plugins
* @param element plugin element
*/
private void createPlugin(
final LoggerRepositoryEx repox,
final List plugins,
final Element element) {
String className = element.getAttribute("class");
if (className.length() > 0)
try {
LogLog.debug(
"About to instantiate plugin of type [" + className + "]");
Plugin plugin = (Plugin)
OptionConverter.instantiateByClassName(
className, org.apache.log4j.plugins.Plugin.class, null);
String pluginName = subst(element.getAttribute("name"));
if (pluginName.length() == 0) {
LogLog.warn(
"No plugin name given for plugin of type " + className + "].");
} else {
plugin.setName(pluginName);
LogLog.debug("plugin named as [" + pluginName + "]");
}
PropertySetter propSetter = new PropertySetter(plugin);
setParams(propSetter, element);
repox.getPluginRegistry().addPlugin(plugin);
plugin.setLoggerRepository(repox);
LogLog.debug("Pushing plugin on to the object stack.");
plugins.add(plugin);
} catch (Exception oops) {
LogLog.error(
"Could not create a plugin. Reported error follows.", oops);
}
}
/**
* File change monitor class.
*/
private static class PluginWatchdog extends FileWatchdog {
/**
* Construct new instance.
* @param filename
*/
public PluginWatchdog(final String filename) {
super(filename);
}
/**
Call configure with the
<code>filename</code> to reconfigure log4j. */
public
void doOnChange() {
new PluginConfigurator().doConfigure(filename,
LogManager.getLoggerRepository());
}
}
}