📄 domconfigurator.cpp
字号:
/*
* 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>
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
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());
}
};
#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 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);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -