This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
The following commit(s) were added to refs/heads/master by this push:
new 2e70889a Prevent abnormal termination when the XML configuration file
has recursive references (#605)
2e70889a is described below
commit 2e70889a4dd9f3f5d4c2a3c7898d7bd9791d822f
Author: Stephen Webb <[email protected]>
AuthorDate: Thu Mar 12 09:41:19 2026 +1100
Prevent abnormal termination when the XML configuration file has recursive
references (#605)
* Detect and ignore a recursive reference to an appender
* Silence ABI check
---
src/main/cpp/domconfigurator.cpp | 514 +++++++++++++++--------
src/main/include/log4cxx/xml/domconfigurator.h | 14 +-
src/test/cpp/asyncappendertestcase.cpp | 70 ++-
src/test/resources/input/xml/recursiveConfig.xml | 38 ++
4 files changed, 433 insertions(+), 203 deletions(-)
diff --git a/src/main/cpp/domconfigurator.cpp b/src/main/cpp/domconfigurator.cpp
index d54a092a..6e1ad59f 100644
--- a/src/main/cpp/domconfigurator.cpp
+++ b/src/main/cpp/domconfigurator.cpp
@@ -14,7 +14,6 @@
* 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/asyncappender.h>
@@ -63,12 +62,75 @@ using namespace LOG4CXX_NS::rolling;
#define MAX_ATTRIBUTE_NAME_LEN 2000
+using FilterStore = std::vector<FilterPtr>;
+
struct DOMConfigurator::DOMConfiguratorPrivate
{
- helpers::Properties props = Configurator::properties();
- spi::LoggerRepositoryPtr repository;
- spi::LoggerFactoryPtr loggerFactory;
+public: // Types
+ struct AppenderStatus
+ {
+ AppenderPtr pAppender;
+ bool activated;
+ };
+ using AppenderMap = std::map<LogString, AppenderStatus>;
+
+public: // Attributes
+ Properties props = Configurator::properties();
+ LoggerRepositoryPtr repository;
+#if LOG4CXX_ABI_VERSION <= 15
+ LoggerFactoryPtr loggerFactory{
std::make_shared<DefaultLoggerFactory>() };
+#else
+ LoggerFactoryPtr loggerFactory{ std::make_shared<LoggerFactory>() };
+#endif
bool appenderAdded{ false };
+ AppenderMap appenders;
+ Pool p;
+ CharsetDecoderPtr utf8Decoder{ CharsetDecoder::getUTF8Decoder() };
+ apr_xml_doc* doc{ nullptr };
+
+public: // ...structor
+ DOMConfiguratorPrivate()
+ : repository(LogManager::getLoggerRepository())
+ {}
+
+ DOMConfiguratorPrivate(const LoggerRepositoryPtr& r)
+ : repository(r)
+ {}
+
+public: // Methods
+ AppenderPtr findAppenderByName(apr_xml_elem* elem, const LogString&
appenderName);
+
+ AppenderPtr findAppenderByReference(apr_xml_elem* appenderRef);
+
+ AppenderPtr parseAppender(apr_xml_elem* appenderElement);
+
+ void parseErrorHandler(apr_xml_elem* element, const AppenderPtr&
appender);
+
+ FilterStore parseFilters(apr_xml_elem* element);
+
+ void parseLogger(apr_xml_elem* loggerElement);
+
+ void parseLoggerFactory(apr_xml_elem* factoryElement);
+
+ ObjectPtr parseTriggeringPolicy(apr_xml_elem* factoryElement);
+
+ RollingPolicyPtr parseRollingPolicy(apr_xml_elem* factoryElement);
+
+ void parseRoot(apr_xml_elem* rootElement);
+
+ void parseChildrenOfLoggerElement(apr_xml_elem* catElement, LoggerPtr
logger, bool isRoot);
+
+ LayoutPtr parseLayout(apr_xml_elem* layout_element);
+
+ void parseLevel(apr_xml_elem* element, LoggerPtr logger, bool isRoot);
+
+ void setParameter(apr_xml_elem* elem, config::PropertySetter&
propSetter);
+
+ void parse(apr_xml_elem* element);
+
+ LogString getAttribute(apr_xml_elem*, const std::string& attrName);
+
+ LogString subst(const LogString& value);
};
namespace LOG4CXX_NS
@@ -141,42 +203,34 @@ IMPLEMENT_LOG4CXX_OBJECT(DOMConfigurator)
#define INTERNAL_COLOR_ATTR "color"
#define THREAD_CONFIG_ATTR "threadConfiguration"
-DOMConfigurator::DOMConfigurator()
- : m_priv(std::make_unique<DOMConfiguratorPrivate>())
-{
-}
+DOMConfigurator::DOMConfigurator() {}
DOMConfigurator::~DOMConfigurator() {}
/**
Used internally to parse appenders by IDREF name.
*/
-AppenderPtr DOMConfigurator::findAppenderByName(LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* element,
- apr_xml_doc* doc,
- const LogString& appenderName,
- AppenderMap& appenders)
+AppenderPtr
DOMConfigurator::DOMConfiguratorPrivate::findAppenderByName(apr_xml_elem*
element, const LogString& appenderName)
{
AppenderPtr appender;
std::string tagName(element->name);
if (tagName == APPENDER_TAG)
{
- if (appenderName == getAttribute(utf8Decoder, element,
NAME_ATTR))
+ if (appenderName == getAttribute(element, NAME_ATTR))
{
- appender = parseAppender(p, utf8Decoder, element, doc,
appenders);
+ appender = parseAppender(element);
}
}
if (element->first_child && !appender)
{
- appender = findAppenderByName(p, utf8Decoder,
element->first_child, doc, appenderName, appenders);
+ appender = findAppenderByName(element->first_child,
appenderName);
}
if (element->next && !appender)
{
- appender = findAppenderByName(p, utf8Decoder, element->next,
doc, appenderName, appenders);
+ appender = findAppenderByName(element->next, appenderName);
}
return appender;
@@ -185,15 +239,10 @@ AppenderPtr
DOMConfigurator::findAppenderByName(LOG4CXX_NS::helpers::Pool& p,
/**
Used internally to parse appenders by IDREF element.
*/
-AppenderPtr DOMConfigurator::findAppenderByReference(
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* appenderRef,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+AppenderPtr
DOMConfigurator::DOMConfiguratorPrivate::findAppenderByReference(apr_xml_elem*
appenderRef)
{
AppenderPtr appender;
- LogString appenderName(subst(getAttribute(utf8Decoder, appenderRef,
REF_ATTR)));
+ LogString appenderName(subst(getAttribute(appenderRef, REF_ATTR)));
if (appenderName.empty())
{
LogString msg(LOG4CXX_STR("["));
@@ -208,16 +257,17 @@ AppenderPtr DOMConfigurator::findAppenderByReference(
if (match != appenders.end())
{
- appender = match->second;
+ if (!match->second.activated)
+ {
+ LogString msg(LOG4CXX_STR("Ignoring recursive reference
to [") + appenderName + LOG4CXX_STR("]"));
+ LogLog::warn(msg);
+ }
+ else
+ appender = match->second.pAppender;
}
else if (doc)
{
- appender = findAppenderByName(p, utf8Decoder, doc->root, doc,
appenderName, appenders);
-
- if (appender)
- {
- appenders.insert(AppenderMap::value_type(appenderName,
appender));
- }
+ appender = findAppenderByName(doc->root, appenderName);
}
if (!appender)
@@ -232,14 +282,10 @@ AppenderPtr DOMConfigurator::findAppenderByReference(
/**
Used internally to parse an appender element.
*/
-AppenderPtr DOMConfigurator::parseAppender(Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* appenderElement,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+AppenderPtr
DOMConfigurator::DOMConfiguratorPrivate::parseAppender(apr_xml_elem*
appenderElement)
{
- LogString className(subst(getAttribute(utf8Decoder, appenderElement,
CLASS_ATTR)));
+ LogString className(subst(getAttribute(appenderElement, CLASS_ATTR)));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Desired ") +
Appender::getStaticClass().getName()
@@ -256,7 +302,8 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
}
PropertySetter propSetter(appender);
- appender->setName(subst(getAttribute(utf8Decoder,
appenderElement, NAME_ATTR)));
+ appender->setName(subst(getAttribute(appenderElement,
NAME_ATTR)));
+ appenders.emplace(appender->getName(), AppenderStatus{appender,
false});
for (apr_xml_elem* currentElement =
appenderElement->first_child;
currentElement;
@@ -268,18 +315,17 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
// Parse appender parameters
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
}
// Set appender layout
else if (tagName == LAYOUT_TAG)
{
- appender->setLayout(parseLayout(p, utf8Decoder,
currentElement));
+
appender->setLayout(parseLayout(currentElement));
}
// Add filters
else if (tagName == FILTER_TAG)
{
- std::vector<LOG4CXX_NS::spi::FilterPtr> filters;
- parseFilters(p, utf8Decoder, currentElement,
filters);
+ auto filters = parseFilters(currentElement);
for (auto& item : filters)
{
@@ -288,11 +334,11 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
}
else if (tagName == ERROR_HANDLER_TAG)
{
- parseErrorHandler(p, utf8Decoder,
currentElement, appender, doc, appenders);
+ parseErrorHandler(currentElement, appender);
}
else if (tagName == ROLLING_POLICY_TAG)
{
- RollingPolicyPtr
rollPolicy(parseRollingPolicy(p, utf8Decoder, currentElement));
+ auto rollPolicy =
parseRollingPolicy(currentElement);
RollingFileAppenderPtr rfa =
LOG4CXX_NS::cast<RollingFileAppender>(appender);
if (rfa != NULL)
@@ -302,7 +348,7 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
}
else if (tagName == TRIGGERING_POLICY_TAG)
{
- ObjectPtr policy(parseTriggeringPolicy(p,
utf8Decoder, currentElement));
+ auto policy =
parseTriggeringPolicy(currentElement);
RollingFileAppenderPtr rfa =
LOG4CXX_NS::cast<RollingFileAppender>(appender);
TriggeringPolicyPtr policyPtr =
LOG4CXX_NS::cast<TriggeringPolicy>(policy);
@@ -326,7 +372,7 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
if
(appender->instanceof(AppenderAttachable::getStaticClass()))
{
AppenderAttachablePtr aa =
LOG4CXX_NS::cast<AppenderAttachable>(appender);
- if (auto delegateAppender =
findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders))
+ if (auto delegateAppender =
findAppenderByReference(currentElement))
{
if (LogLog::isDebugEnabled())
{
@@ -344,9 +390,19 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
+ LOG4CXX_STR(" which does not
implement ") + AppenderAttachable::getStaticClass().getName());
}
}
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown
[") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(appenderElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
+ }
}
propSetter.activate(p);
+ appenders[appender->getName()].activated = true;
return appender;
}
/* Yes, it's ugly. But all of these exceptions point to the same
@@ -361,17 +417,12 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p,
/**
Used internally to parse an {@link ErrorHandler} element.
*/
-void DOMConfigurator::parseErrorHandler(Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* element,
- AppenderPtr& appender,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+void DOMConfigurator::DOMConfiguratorPrivate::parseErrorHandler(apr_xml_elem*
element, const AppenderPtr& appender)
{
ErrorHandlerPtr eh;
std::shared_ptr<Object> obj = OptionConverter::instantiateByClassName(
- subst(getAttribute(utf8Decoder, element, CLASS_ATTR)),
+ subst(getAttribute(element, CLASS_ATTR)),
ErrorHandler::getStaticClass(),
0);
eh = LOG4CXX_NS::cast<ErrorHandler>(obj);
@@ -390,45 +441,48 @@ void DOMConfigurator::parseErrorHandler(Pool& p,
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
}
else if (tagName == APPENDER_REF_TAG)
{
- if (auto appender = findAppenderByReference(p,
utf8Decoder, currentElement, doc, appenders))
+ if (auto appender =
findAppenderByReference(currentElement))
eh->setBackupAppender(appender);
}
else if (tagName == LOGGER_REF)
{
- LogString loggerName(getAttribute(utf8Decoder,
currentElement, REF_ATTR));
- LoggerPtr logger =
m_priv->repository->getLogger(loggerName, m_priv->loggerFactory);
+ LogString
loggerName(getAttribute(currentElement, REF_ATTR));
+ LoggerPtr logger =
this->repository->getLogger(loggerName, this->loggerFactory);
eh->setLogger(logger);
}
else if (tagName == ROOT_REF)
{
- LoggerPtr root =
m_priv->repository->getRootLogger();
+ LoggerPtr root =
this->repository->getRootLogger();
eh->setLogger(root);
}
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown
[") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(element->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
+ }
}
propSetter.activate(p);
- std::shared_ptr<AppenderSkeleton> appSkeleton =
LOG4CXX_NS::cast<AppenderSkeleton>(appender);
-
- if (appSkeleton != 0)
- {
+ if (auto appSkeleton =
LOG4CXX_NS::cast<AppenderSkeleton>(appender))
appSkeleton->setErrorHandler(eh);
- }
}
}
/**
Used internally to parse a filter element.
*/
-void DOMConfigurator::parseFilters(Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* element,
- std::vector<LOG4CXX_NS::spi::FilterPtr>& filters)
+FilterStore
DOMConfigurator::DOMConfiguratorPrivate::parseFilters(apr_xml_elem* element)
{
- LogString clazz = subst(getAttribute(utf8Decoder, element, CLASS_ATTR));
+ FilterStore result;
+ LogString clazz = subst(getAttribute(element, CLASS_ATTR));
FilterPtr filter;
std::shared_ptr<Object> obj =
OptionConverter::instantiateByClassName(clazz,
Filter::getStaticClass(), 0);
@@ -446,39 +500,44 @@ void DOMConfigurator::parseFilters(Pool& p,
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
+ }
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown
[") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(element->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
}
}
propSetter.activate(p);
- filters.push_back(filter);
+ result.push_back(filter);
}
+ return result;
}
/**
Used internally to parse an category or logger element.
*/
-void DOMConfigurator::parseLogger(
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* loggerElement,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+void DOMConfigurator::DOMConfiguratorPrivate::parseLogger(apr_xml_elem*
loggerElement)
{
// Create a new Logger object from the <category> element.
- LogString loggerName = subst(getAttribute(utf8Decoder, loggerElement,
NAME_ATTR));
+ LogString loggerName = subst(getAttribute(loggerElement, NAME_ATTR));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Getting [") + loggerName +
LOG4CXX_STR("]"));
}
- LoggerPtr logger = m_priv->repository->getLogger(loggerName,
m_priv->loggerFactory);
+ LoggerPtr logger = this->repository->getLogger(loggerName,
this->loggerFactory);
// Setting up a logger needs to be an atomic operation, in order
// to protect potential log operations while logger
// configuration is in progress.
bool additivity = OptionConverter::toBoolean(
- subst(getAttribute(utf8Decoder, loggerElement,
ADDITIVITY_ATTR)),
+ subst(getAttribute(loggerElement, ADDITIVITY_ATTR)),
true);
if (LogLog::isDebugEnabled())
@@ -487,18 +546,15 @@ void DOMConfigurator::parseLogger(
(additivity ? LogString(LOG4CXX_STR("true")) :
LogString(LOG4CXX_STR("false"))) + LOG4CXX_STR("]"));
}
logger->setAdditivity(additivity);
- parseChildrenOfLoggerElement(p, utf8Decoder, loggerElement, logger,
false, doc, appenders);
+ parseChildrenOfLoggerElement(loggerElement, logger, false);
}
/**
Used internally to parse the logger factory element.
*/
-void DOMConfigurator::parseLoggerFactory(
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* factoryElement)
+void DOMConfigurator::DOMConfiguratorPrivate::parseLoggerFactory(apr_xml_elem*
factoryElement)
{
- LogString className(subst(getAttribute(utf8Decoder, factoryElement,
CLASS_ATTR)));
+ LogString className(subst(getAttribute(factoryElement, CLASS_ATTR)));
if (className.empty())
{
@@ -520,8 +576,8 @@ void DOMConfigurator::parseLoggerFactory(
, std::make_shared<LoggerFactory>()
#endif
);
- m_priv->loggerFactory = LOG4CXX_NS::cast<LoggerFactory>(obj);
- PropertySetter propSetter(m_priv->loggerFactory);
+ this->loggerFactory = LOG4CXX_NS::cast<LoggerFactory>(obj);
+ PropertySetter propSetter(this->loggerFactory);
for (apr_xml_elem* currentElement = factoryElement->first_child;
currentElement;
@@ -531,7 +587,7 @@ void DOMConfigurator::parseLoggerFactory(
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
}
}
}
@@ -540,33 +596,23 @@ void DOMConfigurator::parseLoggerFactory(
/**
Used internally to parse the root logger element.
*/
-void DOMConfigurator::parseRoot(
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* rootElement,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+void DOMConfigurator::DOMConfiguratorPrivate::parseRoot(apr_xml_elem*
rootElement)
{
- LoggerPtr root = m_priv->repository->getRootLogger();
- parseChildrenOfLoggerElement(p, utf8Decoder, rootElement, root, true,
doc, appenders);
+ LoggerPtr root = this->repository->getRootLogger();
+ parseChildrenOfLoggerElement(rootElement, root, true);
}
/**
Used internally to parse the children of a logger element.
*/
-void DOMConfigurator::parseChildrenOfLoggerElement(
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* loggerElement, LoggerPtr logger, bool isRoot,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+void
DOMConfigurator::DOMConfiguratorPrivate::parseChildrenOfLoggerElement(apr_xml_elem*
loggerElement, LoggerPtr logger, bool isRoot)
{
PropertySetter propSetter(logger);
- auto loggerName = m_priv->repository->getRootLogger() == logger
+ auto loggerName = this->repository->getRootLogger() == logger
? LogString(LOG4CXX_STR("root"))
: logger->getName();
AsyncAppenderPtr async;
- auto lsAsynchronous = subst(getAttribute(utf8Decoder, loggerElement,
ASYNCHRONOUS_ATTR));
+ auto lsAsynchronous = subst(getAttribute(loggerElement,
ASYNCHRONOUS_ATTR));
if (!lsAsynchronous.empty() &&
OptionConverter::toBoolean(lsAsynchronous, true))
{
async = std::make_shared<AsyncAppender>();
@@ -582,7 +628,7 @@ void DOMConfigurator::parseChildrenOfLoggerElement(
if (tagName == APPENDER_REF_TAG)
{
- if (auto appender = findAppenderByReference(p,
utf8Decoder, currentElement, doc, appenders))
+ if (auto appender =
findAppenderByReference(currentElement))
{
if (log4cxx::cast<AsyncAppender>(appender)) //
An explicitly configured AsyncAppender?
async.reset(); // Not required
@@ -599,15 +645,24 @@ void DOMConfigurator::parseChildrenOfLoggerElement(
}
else if (tagName == LEVEL_TAG)
{
- parseLevel(p, utf8Decoder, currentElement, logger,
isRoot);
+ parseLevel(currentElement, logger, isRoot);
}
else if (tagName == PRIORITY_TAG)
{
- parseLevel(p, utf8Decoder, currentElement, logger,
isRoot);
+ parseLevel(currentElement, logger, isRoot);
}
else if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
+ }
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown [") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(loggerElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
}
}
if (async && !newappenders.empty())
@@ -618,14 +673,14 @@ void DOMConfigurator::parseChildrenOfLoggerElement(
+ logger->getName() + LOG4CXX_STR("] is
on"));
}
logger->replaceAppenders({async});
- m_priv->appenderAdded = true;
+ this->appenderAdded = true;
}
else if (newappenders.empty())
logger->removeAllAppenders();
else
{
logger->replaceAppenders(newappenders);
- m_priv->appenderAdded = true;
+ this->appenderAdded = true;
}
propSetter.activate(p);
}
@@ -633,12 +688,9 @@ void DOMConfigurator::parseChildrenOfLoggerElement(
/**
Used internally to parse a layout element.
*/
-LayoutPtr DOMConfigurator::parseLayout (
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* layout_element)
+LayoutPtr DOMConfigurator::DOMConfiguratorPrivate::parseLayout(apr_xml_elem*
layout_element)
{
- LogString className(subst(getAttribute(utf8Decoder, layout_element,
CLASS_ATTR)));
+ LogString className(subst(getAttribute(layout_element, CLASS_ATTR)));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Desired ") +
Layout::getStaticClass().getName()
@@ -659,7 +711,16 @@ LayoutPtr DOMConfigurator::parseLayout (
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
+ }
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown
[") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(layout_element->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
}
}
@@ -676,12 +737,9 @@ LayoutPtr DOMConfigurator::parseLayout (
/**
Used internally to parse a triggering policy
*/
-ObjectPtr DOMConfigurator::parseTriggeringPolicy (
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* policy_element)
+ObjectPtr
DOMConfigurator::DOMConfiguratorPrivate::parseTriggeringPolicy(apr_xml_elem*
policy_element)
{
- LogString className = subst(getAttribute(utf8Decoder, policy_element,
CLASS_ATTR));
+ LogString className = subst(getAttribute(policy_element, CLASS_ATTR));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Desired ") +
TriggeringPolicy::getStaticClass().getName()
@@ -701,15 +759,12 @@ ObjectPtr DOMConfigurator::parseTriggeringPolicy (
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
}
else if (tagName == FILTER_TAG)
{
- std::vector<LOG4CXX_NS::spi::FilterPtr> filters;
- parseFilters(p, utf8Decoder, currentElement,
filters);
- FilterBasedTriggeringPolicyPtr fbtp =
LOG4CXX_NS::cast<FilterBasedTriggeringPolicy>(instance);
-
- if (fbtp != NULL)
+ auto filters = parseFilters(currentElement);
+ if (auto fbtp =
LOG4CXX_NS::cast<FilterBasedTriggeringPolicy>(instance))
{
for (auto& item : filters)
{
@@ -717,6 +772,15 @@ ObjectPtr DOMConfigurator::parseTriggeringPolicy (
}
}
}
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown
[") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(policy_element->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
+ }
}
propSetter.activate(p);
@@ -732,12 +796,9 @@ ObjectPtr DOMConfigurator::parseTriggeringPolicy (
/**
Used internally to parse a triggering policy
*/
-RollingPolicyPtr DOMConfigurator::parseRollingPolicy (
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* policy_element)
+RollingPolicyPtr
DOMConfigurator::DOMConfiguratorPrivate::parseRollingPolicy(apr_xml_elem*
policy_element)
{
- LogString className = subst(getAttribute(utf8Decoder, policy_element,
CLASS_ATTR));
+ LogString className = subst(getAttribute(policy_element, CLASS_ATTR));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Desired ") +
RollingPolicy::getStaticClass().getName()
@@ -757,7 +818,16 @@ RollingPolicyPtr DOMConfigurator::parseRollingPolicy (
if (tagName == PARAM_TAG)
{
- setParameter(p, utf8Decoder, currentElement,
propSetter);
+ setParameter(currentElement, propSetter);
+ }
+ else
+ {
+ LogString msg{ LOG4CXX_STR("Ignoring unknown
[") };
+ utf8Decoder->decode(currentElement->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR("] ");
+ utf8Decoder->decode(policy_element->name,
MAX_ATTRIBUTE_NAME_LEN, msg);
+ msg += LOG4CXX_STR(" element");
+ LogLog::warn(msg);
}
}
@@ -776,10 +846,7 @@ RollingPolicyPtr DOMConfigurator::parseRollingPolicy (
/**
Used internally to parse a level element.
*/
-void DOMConfigurator::parseLevel(
- LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* element, LoggerPtr logger, bool isRoot)
+void DOMConfigurator::DOMConfiguratorPrivate::parseLevel(apr_xml_elem*
element, LoggerPtr logger, bool isRoot)
{
LogString loggerName = logger->getName();
@@ -788,7 +855,7 @@ void DOMConfigurator::parseLevel(
loggerName = LOG4CXX_STR("root");
}
- LogString levelStr(subst(getAttribute(utf8Decoder, element,
VALUE_ATTR)));
+ LogString levelStr(subst(getAttribute(element, VALUE_ATTR)));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Setting [") + loggerName +
LOG4CXX_STR("] level to [") + levelStr + LOG4CXX_STR("]"));
@@ -808,7 +875,7 @@ void DOMConfigurator::parseLevel(
}
else
{
- LogString className(subst(getAttribute(utf8Decoder, element,
CLASS_ATTR)));
+ LogString className(subst(getAttribute(element, CLASS_ATTR)));
if (className.empty())
{
@@ -848,13 +915,10 @@ void DOMConfigurator::parseLevel(
}
}
-void DOMConfigurator::setParameter(LOG4CXX_NS::helpers::Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* elem,
- PropertySetter& propSetter)
+void DOMConfigurator::DOMConfiguratorPrivate::setParameter(apr_xml_elem* elem,
PropertySetter& propSetter)
{
- LogString name(subst(getAttribute(utf8Decoder, elem, NAME_ATTR)));
- LogString value(subst(getAttribute(utf8Decoder, elem, VALUE_ATTR)));
+ LogString name(subst(getAttribute(elem, NAME_ATTR)));
+ LogString value(subst(getAttribute(elem, VALUE_ATTR)));
value = subst(value);
propSetter.setProperty(name, value, p);
}
@@ -868,18 +932,12 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
#endif
)
{
- m_priv->repository = repository ? repository :
LogManager::getLoggerRepository();
+ m_priv = std::make_unique<DOMConfiguratorPrivate>
+ ( repository ? repository : LogManager::getLoggerRepository()
+ );
-#if LOG4CXX_ABI_VERSION <= 15
- m_priv->loggerFactory = std::make_shared<DefaultLoggerFactory>();
-#else
- m_priv->loggerFactory = std::make_shared<LoggerFactory>();
-#endif
-
- Pool p;
apr_file_t* fd;
-
- log4cxx_status_t rv = filename.open(&fd, APR_READ, APR_OS_DEFAULT, p);
+ log4cxx_status_t rv = filename.open(&fd, APR_READ, APR_OS_DEFAULT,
m_priv->p);
if (rv != APR_SUCCESS)
{
@@ -890,16 +948,14 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
}
else
{
- apr_xml_parser* parser = NULL;
- apr_xml_doc* doc = NULL;
-
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Loading configuration file
[")
+ filename.getPath() +
LOG4CXX_STR("]"));
}
- rv = apr_xml_parse_file(p.getAPRPool(), &parser, &doc, fd,
2000);
+ apr_xml_parser* parser = NULL;
+ rv = apr_xml_parse_file(m_priv->p.getAPRPool(), &parser,
&m_priv->doc, fd, 2000);
if (rv != APR_SUCCESS)
{
@@ -925,9 +981,7 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure
}
else
{
- AppenderMap appenders;
- CharsetDecoderPtr
utf8Decoder(CharsetDecoder::getUTF8Decoder());
- parse(p, utf8Decoder, doc->root, doc, appenders);
+ m_priv->parse(m_priv->doc->root);
}
}
@@ -1052,12 +1106,7 @@ spi::ConfigurationStatus
DOMConfigurator::configureAndWatch(const CFStringRef& f
#endif
#endif // LOG4CXX_ABI_VERSION <= 15
-void DOMConfigurator::parse(
- Pool& p,
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* element,
- apr_xml_doc* doc,
- AppenderMap& appenders)
+void DOMConfigurator::DOMConfiguratorPrivate::parse(apr_xml_elem* element)
{
std::string rootElementName(element->name);
@@ -1082,7 +1131,7 @@ void DOMConfigurator::parse(
}
}
- LogString debugAttrib = subst(getAttribute(utf8Decoder, element,
INTERNAL_DEBUG_ATTR));
+ LogString debugAttrib = subst(getAttribute(element,
INTERNAL_DEBUG_ATTR));
// if the log4j.dtd is not specified in the XML file, then the
// "debug" attribute is returned as the empty string.
@@ -1091,26 +1140,26 @@ void DOMConfigurator::parse(
LogLog::setInternalDebugging(OptionConverter::toBoolean(debugAttrib, true));
}
- LogString colorAttrib = subst(getAttribute(utf8Decoder, element,
INTERNAL_COLOR_ATTR));
+ LogString colorAttrib = subst(getAttribute(element,
INTERNAL_COLOR_ATTR));
if (!colorAttrib.empty())
{
LogLog::setColorEnabled(OptionConverter::toBoolean(colorAttrib,
true));
}
- LogString thresholdStr = subst(getAttribute(utf8Decoder, element,
THRESHOLD_ATTR));
+ LogString thresholdStr = subst(getAttribute(element, THRESHOLD_ATTR));
if (!thresholdStr.empty() && thresholdStr != LOG4CXX_STR("NULL"))
{
-
m_priv->repository->setThreshold(OptionConverter::toLevel(thresholdStr,
Level::getAll()));
+
this->repository->setThreshold(OptionConverter::toLevel(thresholdStr,
Level::getAll()));
if (LogLog::isDebugEnabled())
{
LogLog::debug(LOG4CXX_STR("Repository threshold =[")
- + m_priv->repository->getThreshold()->toString()
+ + this->repository->getThreshold()->toString()
+ LOG4CXX_STR("]"));
}
}
- LogString threadSignalValue = subst(getAttribute(utf8Decoder, element,
THREAD_CONFIG_ATTR));
+ LogString threadSignalValue = subst(getAttribute(element,
THREAD_CONFIG_ATTR));
if ( !threadSignalValue.empty() && threadSignalValue !=
LOG4CXX_STR("NULL") )
{
@@ -1150,7 +1199,7 @@ void DOMConfigurator::parse(
if (tagName == CATEGORY_FACTORY_TAG)
{
- parseLoggerFactory(p, utf8Decoder, currentElement);
+ parseLoggerFactory(currentElement);
}
}
@@ -1162,20 +1211,20 @@ void DOMConfigurator::parse(
if (tagName == CATEGORY || tagName == LOGGER)
{
- parseLogger(p, utf8Decoder, currentElement, doc,
appenders);
+ parseLogger(currentElement);
}
else if (tagName == ROOT_TAG)
{
- parseRoot(p, utf8Decoder, currentElement, doc,
appenders);
+ parseRoot(currentElement);
}
}
}
-LogString DOMConfigurator::subst(const LogString& value)
+LogString DOMConfigurator::DOMConfiguratorPrivate::subst(const LogString&
value)
{
try
{
- return OptionConverter::substVars(value, m_priv->props);
+ return OptionConverter::substVars(value, this->props);
}
catch (IllegalArgumentException& e)
{
@@ -1185,10 +1234,7 @@ LogString DOMConfigurator::subst(const LogString& value)
}
-LogString DOMConfigurator::getAttribute(
- LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
- apr_xml_elem* element,
- const std::string& attrName)
+LogString DOMConfigurator::DOMConfiguratorPrivate::getAttribute(apr_xml_elem*
element, const std::string& attrName)
{
LogString attrValue;
@@ -1204,3 +1250,103 @@ LogString DOMConfigurator::getAttribute(
return attrValue;
}
+
+#if LOG4CXX_ABI_VERSION <= 15
+AppenderPtr DOMConfigurator::findAppenderByName(LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ apr_xml_doc* doc,
+ const LogString& appenderName,
+ AppenderMap& appenders)
+{ return AppenderPtr{}; }
+AppenderPtr DOMConfigurator::findAppenderByReference(
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* appenderRef,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{ return AppenderPtr{}; }
+AppenderPtr DOMConfigurator::parseAppender(Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* appenderElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{ return AppenderPtr{}; }
+void DOMConfigurator::parseErrorHandler(Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ AppenderPtr& appender,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{}
+void DOMConfigurator::parseFilters(Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ std::vector<LOG4CXX_NS::spi::FilterPtr>& filters)
+{}
+void DOMConfigurator::parseLogger(
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* loggerElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{}
+void DOMConfigurator::parseLoggerFactory(
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* factoryElement)
+{}
+void DOMConfigurator::parseRoot(
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* rootElement,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{}
+void DOMConfigurator::parseChildrenOfLoggerElement(
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* loggerElement, LoggerPtr logger, bool isRoot,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{}
+LayoutPtr DOMConfigurator::parseLayout (
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* layout_element)
+{ return LayoutPtr{}; }
+ObjectPtr DOMConfigurator::parseTriggeringPolicy (
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* policy_element)
+{ return ObjectPtr{}; }
+RollingPolicyPtr DOMConfigurator::parseRollingPolicy (
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* policy_element)
+{ return RollingPolicyPtr{}; }
+void DOMConfigurator::parseLevel(
+ LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element, LoggerPtr logger, bool isRoot)
+{}
+void DOMConfigurator::setParameter(LOG4CXX_NS::helpers::Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* elem,
+ PropertySetter& propSetter)
+{}
+void DOMConfigurator::parse(
+ Pool& p,
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ apr_xml_doc* doc,
+ AppenderMap& appenders)
+{}
+LogString DOMConfigurator::getAttribute(
+ LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
+ apr_xml_elem* element,
+ const std::string& attrName)
+{ return LogString{}; }
+LogString DOMConfigurator::subst(const LogString& value)
+{ return LogString{}; }
+#endif
\ No newline at end of file
diff --git a/src/main/include/log4cxx/xml/domconfigurator.h
b/src/main/include/log4cxx/xml/domconfigurator.h
index 16ae64b7..e28d9824 100644
--- a/src/main/include/log4cxx/xml/domconfigurator.h
+++ b/src/main/include/log4cxx/xml/domconfigurator.h
@@ -19,18 +19,20 @@
#define _LOG4CXX_XML_DOM_CONFIGURATOR_H
#include <log4cxx/logstring.h>
-#include <map>
+#include <log4cxx/spi/configurator.h>
+#if LOG4CXX_ABI_VERSION <= 15
#include <log4cxx/appender.h>
#include <log4cxx/layout.h>
#include <log4cxx/logger.h>
#include <log4cxx/helpers/properties.h>
-#include <log4cxx/spi/configurator.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/spi/filter.h>
#include <log4cxx/rolling/triggeringpolicy.h>
#include <log4cxx/rolling/rollingpolicy.h>
-#include <log4cxx/file.h>
#include <log4cxx/config/propertysetter.h>
+#include <map>
+#endif
+#include <log4cxx/file.h>
#if LOG4CXX_HAS_DOMCONFIGURATOR
@@ -67,6 +69,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
public:
~DOMConfigurator();
+#if LOG4CXX_ABI_VERSION <= 15
protected:
typedef std::map<LogString, AppenderPtr> AppenderMap;
/**
@@ -205,6 +208,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
apr_xml_elem* element,
apr_xml_doc* doc,
AppenderMap& appenders);
+#endif // LOG4CXX_ABI_VERSION <= 15
public:
DOMConfigurator();
@@ -214,9 +218,9 @@ class LOG4CXX_EXPORT DOMConfigurator :
LOG4CXX_CAST_ENTRY(spi::Configurator)
END_LOG4CXX_CAST_MAP()
+#if LOG4CXX_ABI_VERSION <= 15
DOMConfigurator(LOG4CXX_NS::helpers::Pool& p);
-#if LOG4CXX_ABI_VERSION <= 15
/**
A static version of #doConfigure.
*/
@@ -362,6 +366,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
*/
static spi::ConfigurationStatus configureAndWatch(const File&
configFilename, long delay = 0);
+#if LOG4CXX_ABI_VERSION <= 15
protected:
static LogString getAttribute(
LOG4CXX_NS::helpers::CharsetDecoderPtr& utf8Decoder,
@@ -369,6 +374,7 @@ class LOG4CXX_EXPORT DOMConfigurator :
const std::string& attrName);
LogString subst(const LogString& value);
+#endif
private:
// prevent assignment or copy statements
diff --git a/src/test/cpp/asyncappendertestcase.cpp
b/src/test/cpp/asyncappendertestcase.cpp
index 2c474528..276d6705 100644
--- a/src/test/cpp/asyncappendertestcase.cpp
+++ b/src/test/cpp/asyncappendertestcase.cpp
@@ -48,7 +48,7 @@ struct MyStruct
{
int value;
};
-using OutputStreamType = std::basic_ostream<log4cxx::logchar>;
+using OutputStreamType = std::basic_ostream<LOG4CXX_NS::logchar>;
OutputStreamType& operator<<(OutputStreamType& stream, const MyStruct& data)
{
stream << LOG4CXX_STR("[MyStruct value: ") << data.value <<
LOG4CXX_STR("]");
@@ -56,13 +56,13 @@ OutputStreamType& operator<<(OutputStreamType& stream,
const MyStruct& data)
}
#if FMT_VERSION >= (9 * 10000)
-template <> struct fmt::formatter<MyStruct, log4cxx::logchar> :
fmt::basic_ostream_formatter<log4cxx::logchar> {};
+template <> struct fmt::formatter<MyStruct, LOG4CXX_NS::logchar> :
fmt::basic_ostream_formatter<LOG4CXX_NS::logchar> {};
#endif
#endif
-using namespace log4cxx;
-using namespace log4cxx::helpers;
-using namespace log4cxx::spi;
+using namespace LOG4CXX_NS;
+using namespace LOG4CXX_NS::helpers;
+using namespace LOG4CXX_NS::spi;
class NullPointerAppender : public AppenderSkeleton
{
@@ -75,7 +75,7 @@ class NullPointerAppender : public AppenderSkeleton
/**
* @{inheritDoc}
*/
- void append(const spi::LoggingEventPtr&,
log4cxx::helpers::Pool&) override
+ void append(const spi::LoggingEventPtr&,
LOG4CXX_NS::helpers::Pool&) override
{
throw RuntimeException(LOG4CXX_STR("Intentional
Exception"));
}
@@ -108,7 +108,7 @@ class BlockableVectorAppender : public VectorAppender
/**
* {@inheritDoc}
*/
- void append(const spi::LoggingEventPtr& event,
log4cxx::helpers::Pool& p) override
+ void append(const spi::LoggingEventPtr& event,
LOG4CXX_NS::helpers::Pool& p) override
{
std::lock_guard<std::mutex> lock( blocker );
VectorAppender::append(event, p);
@@ -128,7 +128,7 @@ LOG4CXX_PTR_DEF(BlockableVectorAppender);
class LoggingVectorAppender : public VectorAppender
{
LoggerInstancePtr logger{ "LoggingVectorAppender" };
- void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool&
p) override
+ void append(const spi::LoggingEventPtr& event,
LOG4CXX_NS::helpers::Pool& p) override
{
auto& lsMsg = event->getRenderedMessage();
VectorAppender::append(event, p);
@@ -165,6 +165,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
#if LOG4CXX_HAS_DOMCONFIGURATOR
LOGUNIT_TEST(testXMLConfiguration);
LOGUNIT_TEST(testAsyncLoggerXML);
+ LOGUNIT_TEST(testRecursiveConfiguration);
#endif
LOGUNIT_TEST(testAsyncLoggerProperties);
#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
@@ -503,7 +504,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
LOGUNIT_ASSERT_EQUAL(levelCount[Level::getError()], 1);
LOGUNIT_ASSERT_EQUAL(discardEvent->getLevel(),
Level::getError());
// Check the discard message does not have location info
-
LOGUNIT_ASSERT_EQUAL(log4cxx::spi::LocationInfo::getLocationUnavailable().getClassName(),
+
LOGUNIT_ASSERT_EQUAL(LOG4CXX_NS::spi::LocationInfo::getLocationUnavailable().getClassName(),
discardEvent->getLocationInformation().getClassName());
}
@@ -585,7 +586,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
// Check configuration is as expected
auto root = Logger::getRootLogger();
- auto asyncAppender =
log4cxx::cast<AsyncAppender>(root->getAppender(LOG4CXX_STR("ASYNC")));
+ auto asyncAppender =
LOG4CXX_NS::cast<AsyncAppender>(root->getAppender(LOG4CXX_STR("ASYNC")));
LOGUNIT_ASSERT(asyncAppender);
LOGUNIT_ASSERT_EQUAL(100,
asyncAppender->getBufferSize());
LOGUNIT_ASSERT_EQUAL(false,
asyncAppender->getBlocking());
@@ -602,7 +603,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
asyncAppender->close();
// Check all message were received
- auto vectorAppender =
log4cxx::cast<VectorAppender>(asyncAppender->getAppender(LOG4CXX_STR("VECTOR")));
+ auto vectorAppender =
LOG4CXX_NS::cast<VectorAppender>(asyncAppender->getAppender(LOG4CXX_STR("VECTOR")));
LOGUNIT_ASSERT(vectorAppender);
auto& v = vectorAppender->getVector();
LOGUNIT_ASSERT_EQUAL(LEN, v.size());
@@ -619,7 +620,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
auto root = Logger::getRootLogger();
auto appenders = root->getAllAppenders();
LOGUNIT_ASSERT_EQUAL(1, int(appenders.size()));
- auto asyncAppender =
log4cxx::cast<AsyncAppender>(appenders.front());
+ auto asyncAppender =
LOG4CXX_NS::cast<AsyncAppender>(appenders.front());
LOGUNIT_ASSERT(asyncAppender);
// Log some messages
@@ -631,12 +632,51 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
asyncAppender->close();
// Check all message were received
- auto vectorAppender =
log4cxx::cast<VectorAppender>(asyncAppender->getAppender(LOG4CXX_STR("VECTOR")));
+ auto vectorAppender =
LOG4CXX_NS::cast<VectorAppender>(asyncAppender->getAppender(LOG4CXX_STR("VECTOR")));
LOGUNIT_ASSERT(vectorAppender);
auto& v = vectorAppender->getVector();
LOGUNIT_ASSERT_EQUAL(LEN, v.size());
LOGUNIT_ASSERT(vectorAppender->isClosed());
}
+
+ void testRecursiveConfiguration()
+ {
+ // Configure Log4cxx
+ auto status =
xml::DOMConfigurator::configure("input/xml/recursiveConfig.xml");
+ LOGUNIT_ASSERT_EQUAL(status,
spi::ConfigurationStatus::Configured);
+
+ // Check configuration is as expected
+ auto root = Logger::getRootLogger();
+ auto appenders = root->getAllAppenders();
+ LOGUNIT_ASSERT_EQUAL(1, int(appenders.size()));
+ auto asyncAppender =
LOG4CXX_NS::cast<AsyncAppender>(appenders.front());
+ LOGUNIT_ASSERT(asyncAppender);
+ VectorAppenderPtr vectorAppender;
+ for (auto attachedAppender :
asyncAppender->getAllAppenders())
+ {
+ if (auto async2 =
LOG4CXX_NS::cast<AsyncAppender>(attachedAppender))
+ {
+ for (auto appender :
async2->getAllAppenders())
+ if (vectorAppender =
LOG4CXX_NS::cast<VectorAppender>(appender))
+ break;
+ }
+ }
+ LOGUNIT_ASSERT(vectorAppender);
+
+ // Log some messages
+ size_t LEN = 20;
+ for (size_t i = 0; i < LEN; i++)
+ {
+ LOG4CXX_INFO_ASYNC(root, "message" << i);
+ }
+ std::this_thread::sleep_for( std::chrono::milliseconds(
100 ) );
+ asyncAppender->close();
+
+ // Check all message were received
+ auto& v = vectorAppender->getVector();
+ LOGUNIT_ASSERT_EQUAL(LEN, v.size());
+ LOGUNIT_ASSERT(vectorAppender->isClosed());
+ }
#endif
void testAsyncLoggerProperties()
@@ -649,7 +689,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
auto root = Logger::getRootLogger();
auto appenders = root->getAllAppenders();
LOGUNIT_ASSERT_EQUAL(1, int(appenders.size()));
- auto asyncAppender =
log4cxx::cast<AsyncAppender>(appenders.front());
+ auto asyncAppender =
LOG4CXX_NS::cast<AsyncAppender>(appenders.front());
LOGUNIT_ASSERT(asyncAppender);
// Log some messages
@@ -661,7 +701,7 @@ class AsyncAppenderTestCase : public
AppenderSkeletonTestCase
asyncAppender->close();
// Check all message were received
- auto vectorAppender =
log4cxx::cast<VectorAppender>(asyncAppender->getAppender(LOG4CXX_STR("VECTOR")));
+ auto vectorAppender =
LOG4CXX_NS::cast<VectorAppender>(asyncAppender->getAppender(LOG4CXX_STR("VECTOR")));
LOGUNIT_ASSERT(vectorAppender);
auto& v = vectorAppender->getVector();
LOGUNIT_ASSERT_EQUAL(LEN, v.size());
diff --git a/src/test/resources/input/xml/recursiveConfig.xml
b/src/test/resources/input/xml/recursiveConfig.xml
new file mode 100644
index 00000000..716b04c4
--- /dev/null
+++ b/src/test/resources/input/xml/recursiveConfig.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<!--
+ 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.
+
+-->
+
+<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
+
+ <appender name="VECTOR" class="org.apache.log4j.VectorAppender"/>
+
+ <appender name="ASYNC1" class="org.apache.log4j.AsyncAppender">
+ <appender-ref ref="ASYNC2"/>
+ <appender-ref ref="VECTOR"/>
+ </appender>
+
+ <appender name="ASYNC2" class="org.apache.log4j.AsyncAppender">
+ <appender-ref ref="ASYNC1"/>
+ </appender>
+
+ <root>
+ <level value="DEBUG"/>
+ <appender-ref ref="ASYNC2" />
+ </root>
+</log4j:configuration>