/*
 * 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.
 */

#include <log4cxx/logstring.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/appender.h>
#include <log4cxx/layout.h>
#include <log4cxx/logger.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/level.h>
#include <log4cxx/spi/filter.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/loader.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/config/propertysetter.h>
#include <log4cxx/spi/errorhandler.h>
#include <log4cxx/spi/loggerfactory.h>
#include <log4cxx/defaultloggerfactory.h>
#include <log4cxx/helpers/filewatchdog.h>
#include <log4cxx/helpers/synchronized.h>
#include <log4cxx/spi/loggerrepository.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/helpers/pool.h>
#include <sstream>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/rolling/filterbasedtriggeringpolicy.h>
#include <apr_xml.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/net/smtpappender.h>
#include <log4cxx/helpers/messagebuffer.h>

#define LOG4CXX 1
#include <log4cxx/helpers/aprinitializer.h>

using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;
using namespace log4cxx::config;
using namespace log4cxx::rolling;


#if APR_HAS_THREADS
namespace log4cxx
{
namespace xml
{
class XMLWatchdog  : public FileWatchdog
{
	public:
		XMLWatchdog(const File& filename) : FileWatchdog(filename)
		{
		}

		/**
		Call DOMConfigurator#doConfigure with the
		<code>filename</code> to reconfigure log4cxx.
		*/
		void doOnChange()
		{
			DOMConfigurator().doConfigure(file,
				LogManager::getLoggerRepository());
		}
};
}
}
XMLWatchdog* DOMConfigurator::xdog = NULL;
#endif


IMPLEMENT_LOG4CXX_OBJECT(DOMConfigurator)

#define CONFIGURATION_TAG "log4j:configuration"
#define OLD_CONFIGURATION_TAG "configuration"
#define APPENDER_TAG "appender"
#define APPENDER_REF_TAG "appender-ref"
#define PARAM_TAG "param"
#define LAYOUT_TAG "layout"
#define ROLLING_POLICY_TAG "rollingPolicy"
#define TRIGGERING_POLICY_TAG "triggeringPolicy"
#define CATEGORY "category"
#define LOGGER "logger"
#define LOGGER_REF "logger-ref"
#define CATEGORY_FACTORY_TAG "categoryFactory"
#define NAME_ATTR "name"
#define CLASS_ATTR "class"
#define VALUE_ATTR "value"
#define ROOT_TAG "root"
#define ROOT_REF "root-ref"
#define LEVEL_TAG "level"
#define PRIORITY_TAG "priority"
#define FILTER_TAG "filter"
#define ERROR_HANDLER_TAG "errorHandler"
#define REF_ATTR "ref"
#define ADDITIVITY_ATTR "additivity"
#define THRESHOLD_ATTR "threshold"
#define STRINGSTREAM_ATTR "stringstream"
#define CONFIG_DEBUG_ATTR "configDebug"
#define INTERNAL_DEBUG_ATTR "debug"

DOMConfigurator::DOMConfigurator()
	: props(), repository()
{
}

void DOMConfigurator::addRef() const
{
	ObjectImpl::addRef();
}

void DOMConfigurator::releaseRef() const
{
	ObjectImpl::releaseRef();
}

/**
Used internally to parse appenders by IDREF name.
*/
AppenderPtr DOMConfigurator::findAppenderByName(log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* element,
	apr_xml_doc* doc,
	const LogString& appenderName,
	AppenderMap& appenders)
{
	AppenderPtr appender;
	std::string tagName(element->name);

	if (tagName == APPENDER_TAG)
	{
		if (appenderName == getAttribute(utf8Decoder, element, NAME_ATTR))
		{
			appender = parseAppender(p, utf8Decoder, element, doc, appenders);
		}
	}

	if (element->first_child && !appender)
	{
		appender = findAppenderByName(p, utf8Decoder, element->first_child, doc, appenderName, appenders);
	}

	if (element->next && !appender)
	{
		appender = findAppenderByName(p, utf8Decoder, element->next, doc, appenderName, appenders);
	}

	return appender;
}

/**
 Used internally to parse appenders by IDREF element.
*/
AppenderPtr DOMConfigurator::findAppenderByReference(
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* appenderRef,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{
	LogString appenderName(subst(getAttribute(utf8Decoder, appenderRef, REF_ATTR)));
	AppenderMap::const_iterator match = appenders.find(appenderName);
	AppenderPtr appender;

	if (match != appenders.end())
	{
		appender = match->second;
	}
	else if (doc)
	{
		appender = findAppenderByName(p, utf8Decoder, doc->root, doc, appenderName, appenders);

		if (appender)
		{
			appenders.insert(AppenderMap::value_type(appenderName, appender));
		}
	}

	if (!appender)
	{
		LogLog::error(LOG4CXX_STR("No appender named [") +
			appenderName + LOG4CXX_STR("] could be found."));
	}

	return appender;
}

/**
Used internally to parse an appender element.
*/
AppenderPtr DOMConfigurator::parseAppender(Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* appenderElement,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{

	LogString className(subst(getAttribute(utf8Decoder, appenderElement, CLASS_ATTR)));
	LogLog::debug(LOG4CXX_STR("Class name: [") + className + LOG4CXX_STR("]"));

	try
	{
		ObjectPtr instance = Loader::loadClass(className).newInstance();
		AppenderPtr appender = instance;
		PropertySetter propSetter(appender);

		appender->setName(subst(getAttribute(utf8Decoder, appenderElement, NAME_ATTR)));

		for (apr_xml_elem* currentElement = appenderElement->first_child;
			currentElement;
			currentElement = currentElement->next)
		{

			std::string tagName(currentElement->name);

			// Parse appender parameters
			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
			// Set appender layout
			else if (tagName == LAYOUT_TAG)
			{
				appender->setLayout(parseLayout(p, utf8Decoder, currentElement));
			}
			// Add filters
			else if (tagName == FILTER_TAG)
			{
				std::vector<log4cxx::spi::FilterPtr> filters;
				parseFilters(p, utf8Decoder, currentElement, filters);

				for (std::vector<log4cxx::spi::FilterPtr>::iterator iter = filters.begin();
					iter != filters.end();
					iter++)
				{
					appender->addFilter(*iter);
				}
			}
			else if (tagName == ERROR_HANDLER_TAG)
			{
				parseErrorHandler(p, utf8Decoder, currentElement, appender, doc, appenders);
			}
			else if (tagName == ROLLING_POLICY_TAG)
			{
				RollingPolicyPtr rollPolicy(parseRollingPolicy(p, utf8Decoder, currentElement));
				RollingFileAppenderPtr rfa(appender);

				if (rfa != NULL)
				{
					rfa->setRollingPolicy(rollPolicy);
				}
			}
			else if (tagName == TRIGGERING_POLICY_TAG)
			{
				ObjectPtr policy(parseTriggeringPolicy(p, utf8Decoder, currentElement));
				RollingFileAppenderPtr rfa(appender);

				if (rfa != NULL)
				{
					rfa->setTriggeringPolicy(policy);
				}
				else
				{
					log4cxx::net::SMTPAppenderPtr smtpa(appender);

					if (smtpa != NULL)
					{
						log4cxx::spi::TriggeringEventEvaluatorPtr evaluator(policy);
						smtpa->setEvaluator(evaluator);
					}
				}
			}
			else if (tagName == APPENDER_REF_TAG)
			{
				LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));

				if (appender->instanceof(AppenderAttachable::getStaticClass()))
				{
					AppenderAttachablePtr aa(appender);
					LogLog::debug(LOG4CXX_STR("Attaching appender named [") +
						refName + LOG4CXX_STR("] to appender named [") +
						appender->getName() + LOG4CXX_STR("]."));
					aa->addAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
				}
				else
				{
					LogLog::error(LOG4CXX_STR("Requesting attachment of appender named [") +
						refName + LOG4CXX_STR("] to appender named [") + appender->getName() +
						LOG4CXX_STR("] which does not implement AppenderAttachable."));
				}
			}
		}

		propSetter.activate(p);
		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(LOG4CXX_STR("Could not create an Appender. Reported error follows."),
			oops);
		return 0;
	}
}

/**
Used internally to parse an {@link ErrorHandler} element.
*/
void DOMConfigurator::parseErrorHandler(Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* element,
	AppenderPtr& appender,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{

	ErrorHandlerPtr eh = OptionConverter::instantiateByClassName(
			subst(getAttribute(utf8Decoder, element, CLASS_ATTR)),
			ErrorHandler::getStaticClass(),
			0);

	if (eh != 0)
	{
		eh->setAppender(appender);

		PropertySetter propSetter(eh);

		for (apr_xml_elem* currentElement = element->first_child;
			currentElement;
			currentElement = currentElement->next)
		{
			std::string tagName(currentElement->name);

			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
			else if (tagName == APPENDER_REF_TAG)
			{
				eh->setBackupAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders));
			}
			else if (tagName == LOGGER_REF)
			{
				LogString loggerName(getAttribute(utf8Decoder, currentElement, REF_ATTR));
				LoggerPtr logger = repository->getLogger(loggerName, loggerFactory);
				eh->setLogger(logger);
			}
			else if (tagName == ROOT_REF)
			{
				LoggerPtr root = repository->getRootLogger();
				eh->setLogger(root);
			}
		}

		propSetter.activate(p);
		ObjectPtrT<AppenderSkeleton> appSkeleton(appender);

		if (appSkeleton != 0)
		{
			appSkeleton->setErrorHandler(eh);
		}
	}
}

/**
 Used internally to parse a filter element.
*/
void DOMConfigurator::parseFilters(Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* element,
	std::vector<log4cxx::spi::FilterPtr>& filters)
{
	LogString clazz = subst(getAttribute(utf8Decoder, element, CLASS_ATTR));
	FilterPtr filter = OptionConverter::instantiateByClassName(clazz,
			Filter::getStaticClass(), 0);

	if (filter != 0)
	{
		PropertySetter propSetter(filter);

		for (apr_xml_elem* currentElement = element->first_child;
			currentElement;
			currentElement = currentElement->next)
		{
			std::string tagName(currentElement->name);

			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
		}

		propSetter.activate(p);
		filters.push_back(filter);
	}
}

/**
Used internally to parse an category or logger element.
*/
void DOMConfigurator::parseLogger(
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* loggerElement,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{
	// Create a new Logger object from the <category> element.
	LogString loggerName = subst(getAttribute(utf8Decoder, loggerElement, NAME_ATTR));

	LogLog::debug(LOG4CXX_STR("Retreiving an instance of Logger."));
	LoggerPtr logger = repository->getLogger(loggerName, loggerFactory);

	// Setting up a logger needs to be an atomic operation, in order
	// to protect potential log operations while logger
	// configuration is in progress.
	LOCK_W sync(logger->getMutex());
	bool additivity = OptionConverter::toBoolean(
			subst(getAttribute(utf8Decoder, loggerElement, ADDITIVITY_ATTR)),
			true);

	LogLog::debug(LOG4CXX_STR("Setting [") + logger->getName() + LOG4CXX_STR("] additivity to [") +
		(additivity ? LogString(LOG4CXX_STR("true")) : LogString(LOG4CXX_STR("false"))) + LOG4CXX_STR("]."));
	logger->setAdditivity(additivity);
	parseChildrenOfLoggerElement(p, utf8Decoder, loggerElement, logger, false, doc, appenders);
}

/**
 Used internally to parse the logger factory element.
*/
void DOMConfigurator::parseLoggerFactory(
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* factoryElement)
{
	LogString className(subst(getAttribute(utf8Decoder, factoryElement, CLASS_ATTR)));

	if (className.empty())
	{
		LogLog::error(LOG4CXX_STR("Logger Factory tag class attribute not found."));
		LogLog::debug(LOG4CXX_STR("No Logger Factory configured."));
	}
	else
	{
		LogLog::debug(LOG4CXX_STR("Desired logger factory: [") + className + LOG4CXX_STR("]"));
		loggerFactory = OptionConverter::instantiateByClassName(
				className,
				LoggerFactory::getStaticClass(),
				0);
		PropertySetter propSetter(loggerFactory);

		for (apr_xml_elem* currentElement = factoryElement->first_child;
			currentElement;
			currentElement = currentElement->next)
		{
			std::string tagName(currentElement->name);

			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
		}
	}
}

/**
 Used internally to parse the root logger element.
*/
void DOMConfigurator::parseRoot(
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* rootElement,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{
	LoggerPtr root = repository->getRootLogger();
	// logger configuration needs to be atomic
	LOCK_W sync(root->getMutex());
	parseChildrenOfLoggerElement(p, utf8Decoder, rootElement, root, true, doc, appenders);
}

/**
 Used internally to parse the children of a logger element.
*/
void DOMConfigurator::parseChildrenOfLoggerElement(
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* loggerElement, LoggerPtr logger, bool isRoot,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{

	PropertySetter propSetter(logger);

	// Remove all existing appenders from logger. They will be
	// reconstructed if need be.
	logger->removeAllAppenders();


	for (apr_xml_elem* currentElement = loggerElement->first_child;
		currentElement;
		currentElement = currentElement->next)
	{
		std::string tagName(currentElement->name);

		if (tagName == APPENDER_REF_TAG)
		{
			AppenderPtr appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders);
			LogString refName =  subst(getAttribute(utf8Decoder, currentElement, REF_ATTR));

			if (appender != 0)
			{
				LogLog::debug(LOG4CXX_STR("Adding appender named [") + refName +
					LOG4CXX_STR("] to logger [") + logger->getName() + LOG4CXX_STR("]."));
			}
			else
			{
				LogLog::debug(LOG4CXX_STR("Appender named [") + refName +
					LOG4CXX_STR("] not found."));
			}

			logger->addAppender(appender);

		}
		else if (tagName == LEVEL_TAG)
		{
			parseLevel(p, utf8Decoder, currentElement, logger, isRoot);
		}
		else if (tagName == PRIORITY_TAG)
		{
			parseLevel(p, utf8Decoder, currentElement, logger, isRoot);
		}
		else if (tagName == PARAM_TAG)
		{
			setParameter(p, utf8Decoder, currentElement, propSetter);
		}
	}

	propSetter.activate(p);
}

/**
 Used internally to parse a layout element.
*/
LayoutPtr DOMConfigurator::parseLayout (
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* layout_element)
{
	LogString className(subst(getAttribute(utf8Decoder, layout_element, CLASS_ATTR)));
	LogLog::debug(LOG4CXX_STR("Parsing layout of class: \"") + className + LOG4CXX_STR("\""));

	try
	{
		ObjectPtr instance = Loader::loadClass(className).newInstance();
		LayoutPtr layout = instance;
		PropertySetter propSetter(layout);

		for (apr_xml_elem* currentElement = layout_element->first_child;
			currentElement;
			currentElement = currentElement->next)
		{
			std::string tagName(currentElement->name);

			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
		}

		propSetter.activate(p);
		return layout;
	}
	catch (Exception& oops)
	{
		LogLog::error(LOG4CXX_STR("Could not create the Layout. Reported error follows."),
			oops);
		return 0;
	}
}

/**
 Used internally to parse a triggering policy
*/
ObjectPtr DOMConfigurator::parseTriggeringPolicy (
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* layout_element)
{
	LogString className = subst(getAttribute(utf8Decoder, layout_element, CLASS_ATTR));
	LogLog::debug(LOG4CXX_STR("Parsing triggering policy of class: \"") + className + LOG4CXX_STR("\""));

	try
	{
		ObjectPtr instance = Loader::loadClass(className).newInstance();
		PropertySetter propSetter(instance);

		for (apr_xml_elem* currentElement = layout_element->first_child;
			currentElement;
			currentElement = currentElement->next)
		{
			std::string tagName(currentElement->name);

			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
			else if (tagName == FILTER_TAG)
			{
				std::vector<log4cxx::spi::FilterPtr> filters;
				parseFilters(p, utf8Decoder, currentElement, filters);
				FilterBasedTriggeringPolicyPtr fbtp(instance);

				if (fbtp != NULL)
				{
					for (std::vector<log4cxx::spi::FilterPtr>::iterator iter = filters.begin();
						iter != filters.end();
						iter++)
					{
						fbtp->addFilter(*iter);
					}
				}
			}
		}

		propSetter.activate(p);
		return instance;
	}
	catch (Exception& oops)
	{
		LogLog::error(LOG4CXX_STR("Could not create the TriggeringPolicy. Reported error follows."),
			oops);
		return 0;
	}
}

/**
 Used internally to parse a triggering policy
*/
RollingPolicyPtr DOMConfigurator::parseRollingPolicy (
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* layout_element)
{
	LogString className = subst(getAttribute(utf8Decoder, layout_element, CLASS_ATTR));
	LogLog::debug(LOG4CXX_STR("Parsing rolling policy of class: \"") + className + LOG4CXX_STR("\""));

	try
	{
		ObjectPtr instance = Loader::loadClass(className).newInstance();
		RollingPolicyPtr layout = instance;
		PropertySetter propSetter(layout);

		for (apr_xml_elem* currentElement = layout_element->first_child;
			currentElement;
			currentElement = currentElement->next)
		{
			std::string tagName(currentElement->name);

			if (tagName == PARAM_TAG)
			{
				setParameter(p, utf8Decoder, currentElement, propSetter);
			}
		}

		propSetter.activate(p);
		return layout;
	}
	catch (Exception& oops)
	{
		LogLog::error(LOG4CXX_STR("Could not create the RollingPolicy. Reported error follows."),
			oops);
		return 0;
	}
}



/**
 Used internally to parse a level  element.
*/
void DOMConfigurator::parseLevel(
	log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* element, LoggerPtr logger, bool isRoot)
{
	LogString loggerName = logger->getName();

	if (isRoot)
	{
		loggerName = LOG4CXX_STR("root");
	}

	LogString levelStr(subst(getAttribute(utf8Decoder, element, VALUE_ATTR)));
	LogLog::debug(LOG4CXX_STR("Level value for ") + loggerName + LOG4CXX_STR(" is [") + levelStr + LOG4CXX_STR("]."));

	if (StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited"))
		|| StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("NULL"), LOG4CXX_STR("null")))
	{
		if (isRoot)
		{
			LogLog::error(LOG4CXX_STR("Root level cannot be inherited. Ignoring directive."));
		}
		else
		{
			logger->setLevel(0);
		}
	}
	else
	{
		LogString className(subst(getAttribute(utf8Decoder, element, CLASS_ATTR)));

		if (className.empty())
		{
			logger->setLevel(OptionConverter::toLevel(levelStr, Level::getDebug()));
		}
		else
		{
			LogLog::debug(LOG4CXX_STR("Desired Level sub-class: [") + className + LOG4CXX_STR("]"));

			try
			{
				Level::LevelClass& levelClass =
					(Level::LevelClass&)Loader::loadClass(className);
				LevelPtr level = levelClass.toLevel(levelStr);
				logger->setLevel(level);
			}
			catch (Exception& oops)
			{
				LogLog::error(
					LOG4CXX_STR("Could not create level [") + levelStr +
					LOG4CXX_STR("]. Reported error follows."),
					oops);

				return;
			}
			catch (...)
			{
				LogLog::error(
					LOG4CXX_STR("Could not create level [") + levelStr);

				return;
			}
		}
	}

	LogLog::debug(loggerName + LOG4CXX_STR(" level set to ") +
		logger->getEffectiveLevel()->toString());
}

void DOMConfigurator::setParameter(log4cxx::helpers::Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* elem,
	PropertySetter& propSetter)
{
	LogString name(subst(getAttribute(utf8Decoder, elem, NAME_ATTR)));
	LogString value(subst(getAttribute(utf8Decoder, elem, VALUE_ATTR)));
	value = subst(value);
	propSetter.setProperty(name, value, p);
}

void DOMConfigurator::doConfigure(const File& filename, spi::LoggerRepositoryPtr& repository1)
{
	repository1->setConfigured(true);
	this->repository = repository1;
	LogString msg(LOG4CXX_STR("DOMConfigurator configuring file "));
	msg.append(filename.getPath());
	msg.append(LOG4CXX_STR("..."));
	LogLog::debug(msg);

	loggerFactory = new DefaultLoggerFactory();

	Pool p;
	apr_file_t* fd;

	log4cxx_status_t rv = filename.open(&fd, APR_READ, APR_OS_DEFAULT, p);

	if (rv != APR_SUCCESS)
	{
		LogString msg2(LOG4CXX_STR("Could not open file ["));
		msg2.append(filename.getPath());
		msg2.append(LOG4CXX_STR("]."));
		LogLog::error(msg2);
	}
	else
	{
		apr_xml_parser* parser = NULL;
		apr_xml_doc* doc = NULL;
		rv = apr_xml_parse_file(p.getAPRPool(), &parser, &doc, fd, 2000);

		if (rv != APR_SUCCESS)
		{
			char errbuf[2000];
			char errbufXML[2000];
			LogString msg2(LOG4CXX_STR("Error parsing file ["));
			msg2.append(filename.getPath());
			msg2.append(LOG4CXX_STR("], "));
			apr_strerror(rv, errbuf, sizeof(errbuf));
			LOG4CXX_DECODE_CHAR(lerrbuf, std::string(errbuf));
			msg2.append(lerrbuf);

			if (parser)
			{
				apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML));
				LOG4CXX_DECODE_CHAR(lerrbufXML, std::string(errbufXML));
				msg2.append(lerrbufXML);
			}

			LogLog::error(msg2);
		}
		else
		{
			AppenderMap appenders;
			CharsetDecoderPtr utf8Decoder(CharsetDecoder::getUTF8Decoder());
			parse(p, utf8Decoder, doc->root, doc, appenders);
		}
	}
}

void DOMConfigurator::configure(const std::string& filename)
{
	File file(filename);
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
}

#if LOG4CXX_WCHAR_T_API
void DOMConfigurator::configure(const std::wstring& filename)
{
	File file(filename);
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
}
#endif

#if LOG4CXX_UNICHAR_API
void DOMConfigurator::configure(const std::basic_string<UniChar>& filename)
{
	File file(filename);
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
}
#endif

#if LOG4CXX_CFSTRING_API
void DOMConfigurator::configure(const CFStringRef& filename)
{
	File file(filename);
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
}
#endif


void DOMConfigurator::configureAndWatch(const std::string& filename)
{
	configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
}

#if LOG4CXX_WCHAR_T_API
void DOMConfigurator::configureAndWatch(const std::wstring& filename)
{
	configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
}
#endif

#if LOG4CXX_UNICHAR_API
void DOMConfigurator::configureAndWatch(const std::basic_string<UniChar>& filename)
{
	configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
}
#endif

#if LOG4CXX_CFSTRING_API
void DOMConfigurator::configureAndWatch(const CFStringRef& filename)
{
	configureAndWatch(filename, FileWatchdog::DEFAULT_DELAY);
}
#endif

void DOMConfigurator::configureAndWatch(const std::string& filename, long delay)
{
	File file(filename);
#if APR_HAS_THREADS

	if ( xdog )
	{
		APRInitializer::unregisterCleanup(xdog);
		delete xdog;
	}

	xdog = new XMLWatchdog(file);
	APRInitializer::registerCleanup(xdog);
	xdog->setDelay(delay);
	xdog->start();
#else
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
#endif
}

#if LOG4CXX_WCHAR_T_API
void DOMConfigurator::configureAndWatch(const std::wstring& filename, long delay)
{
	File file(filename);
#if APR_HAS_THREADS

	if ( xdog )
	{
		APRInitializer::unregisterCleanup(xdog);
		delete xdog;
	}

	xdog = new XMLWatchdog(file);
	APRInitializer::registerCleanup(xdog);
	xdog->setDelay(delay);
	xdog->start();
#else
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
#endif
}
#endif

#if LOG4CXX_UNICHAR_API
void DOMConfigurator::configureAndWatch(const std::basic_string<UniChar>& filename, long delay)
{
	File file(filename);
#if APR_HAS_THREADS

	if ( xdog )
	{
		APRInitializer::unregisterCleanup(xdog);
		delete xdog;
	}

	xdog = new XMLWatchdog(file);
	APRInitializer::registerCleanup(xdog);
	xdog->setDelay(delay);
	xdog->start();
#else
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
#endif
}
#endif

#if LOG4CXX_CFSTRING_API
void DOMConfigurator::configureAndWatch(const CFStringRef& filename, long delay)
{
	File file(filename);
#if APR_HAS_THREADS

	if ( xdog )
	{
		APRInitializer::unregisterCleanup(xdog);
		delete xdog;
	}

	xdog = new XMLWatchdog(file);
	APRInitializer::registerCleanup(xdog);
	xdog->setDelay(delay);
	xdog->start();
#else
	DOMConfigurator().doConfigure(file, LogManager::getLoggerRepository());
#endif
}
#endif

void DOMConfigurator::parse(
	Pool& p,
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* element,
	apr_xml_doc* doc,
	AppenderMap& appenders)
{
	std::string rootElementName(element->name);

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

	LogString debugAttrib = subst(getAttribute(utf8Decoder, element, INTERNAL_DEBUG_ATTR));

	static const LogString NuLL(LOG4CXX_STR("NULL"));
	LogLog::debug(LOG4CXX_STR("debug attribute= \"") + debugAttrib + LOG4CXX_STR("\"."));

	// if the log4j.dtd is not specified in the XML file, then the
	// "debug" attribute is returned as the empty string.
	if (!debugAttrib.empty() && debugAttrib != NuLL)
	{
		LogLog::setInternalDebugging(OptionConverter::toBoolean(debugAttrib, true));
	}
	else
	{
		LogLog::debug(LOG4CXX_STR("Ignoring internalDebug attribute."));
	}


	LogString confDebug = subst(getAttribute(utf8Decoder, element, CONFIG_DEBUG_ATTR));

	if (!confDebug.empty() && confDebug != NuLL)
	{
		LogLog::warn(LOG4CXX_STR("The \"configDebug\" attribute is deprecated."));
		LogLog::warn(LOG4CXX_STR("Use the \"internalDebug\" attribute instead."));
		LogLog::setInternalDebugging(OptionConverter::toBoolean(confDebug, true));
	}

	LogString thresholdStr = subst(getAttribute(utf8Decoder, element, THRESHOLD_ATTR));
	LogLog::debug(LOG4CXX_STR("Threshold =\"") + thresholdStr + LOG4CXX_STR("\"."));

	if (!thresholdStr.empty() && thresholdStr != NuLL)
	{
		repository->setThreshold(thresholdStr);
	}

	LogString strstrValue = subst(getAttribute(utf8Decoder, element, STRINGSTREAM_ATTR));
	LogLog::debug(LOG4CXX_STR("Stringstream =\"") + strstrValue + LOG4CXX_STR("\"."));

	if (!strstrValue.empty() && strstrValue != NuLL)
	{
		MessageBufferUseStaticStream();
	}

	apr_xml_elem* currentElement;

	for (currentElement = element->first_child;
		currentElement;
		currentElement = currentElement->next)
	{
		std::string tagName(currentElement->name);

		if (tagName == CATEGORY_FACTORY_TAG)
		{
			parseLoggerFactory(p, utf8Decoder, currentElement);
		}
	}

	for (currentElement = element->first_child;
		currentElement;
		currentElement = currentElement->next)
	{
		std::string tagName(currentElement->name);

		if (tagName == CATEGORY || tagName == LOGGER)
		{
			parseLogger(p, utf8Decoder, currentElement, doc, appenders);
		}
		else if (tagName == ROOT_TAG)
		{
			parseRoot(p, utf8Decoder, currentElement, doc, appenders);
		}
	}
}

LogString DOMConfigurator::subst(const LogString& value)
{
	try
	{
		return OptionConverter::substVars(value, props);
	}
	catch (IllegalArgumentException& e)
	{
		LogLog::warn(LOG4CXX_STR("Could not perform variable substitution."), e);
		return value;
	}
}


LogString DOMConfigurator::getAttribute(
	log4cxx::helpers::CharsetDecoderPtr& utf8Decoder,
	apr_xml_elem* element,
	const std::string& attrName)
{
	LogString attrValue;

	for (apr_xml_attr* attr = element->attr;
		attr;
		attr = attr->next)
	{
		if (attrName == attr->name)
		{
			ByteBuffer buf((char*) attr->value, strlen(attr->value));
			utf8Decoder->decode(buf, attrValue);
		}
	}

	return attrValue;
}
