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 a4ebf8f8 Require the configuration file specify an appender to be valid (#533) a4ebf8f8 is described below commit a4ebf8f81f294bb85020db1fb6f067d1a3abe24f Author: Stephen Webb <stephen.w...@ieee.org> AuthorDate: Thu Sep 4 10:22:57 2025 +1000 Require the configuration file specify an appender to be valid (#533) * Simplify DOMConfigurator * Require that a properties file has an appender to be valid * In the next ABI, require that a properties file adds an appender to be valid * Log a warning when the configuration file did not add an appender * Upgrade sonarcube version to avoid Github action command injection vulnerability * Improve the layout of a logged XML syntax error --- .github/workflows/sonarcloud.yml | 4 +- src/main/cpp/charsetdecoder.cpp | 7 ++ src/main/cpp/defaultconfigurator.cpp | 1 - src/main/cpp/domconfigurator.cpp | 137 +++++++++++---------- src/main/cpp/propertyconfigurator.cpp | 99 ++++++++++----- src/main/include/log4cxx/helpers/charsetdecoder.h | 22 +++- src/main/include/log4cxx/propertyconfigurator.h | 7 +- src/test/cpp/asyncappendertestcase.cpp | 3 +- src/test/cpp/customlogger/xloggertestcase.cpp | 3 +- src/test/cpp/db/odbcappendertestcase.cpp | 3 +- src/test/cpp/fmttest.cpp | 9 +- src/test/cpp/helpers/messagebuffertest.cpp | 3 +- src/test/cpp/hierarchythresholdtestcase.cpp | 24 ++-- src/test/cpp/l7dtestcase.cpp | 3 +- src/test/cpp/locationdisabledtest.cpp | 3 +- src/test/cpp/locationtest.cpp | 3 +- src/test/cpp/ndctestcase.cpp | 3 +- src/test/cpp/net/smtpappendertestcase.cpp | 6 +- src/test/cpp/net/xmlsocketappendertestcase.cpp | 3 +- src/test/cpp/patternlayouttest.cpp | 45 ++++--- src/test/cpp/propertyconfiguratortest.cpp | 9 +- src/test/cpp/rolling/filterbasedrollingtest.cpp | 5 +- src/test/cpp/varia/errorhandlertestcase.cpp | 6 +- src/test/cpp/xml/customleveltestcase.cpp | 10 +- src/test/cpp/xml/domtestcase.cpp | 51 ++++++-- src/test/resources/input/xml/DOMTestCase5_bad0.xml | 22 ++++ src/test/resources/input/xml/DOMTestCase5_bad1.xml | 33 +++++ src/test/resources/input/xml/DOMTestCase5_bad2.xml | 33 +++++ src/test/resources/input/xml/DOMTestCase5_bad3.xml | 22 ++++ src/test/resources/input/xml/DOMTestCase5_good.xml | 33 +++++ 30 files changed, 449 insertions(+), 163 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 526b6e41..85a304e6 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -55,7 +55,7 @@ jobs: sudo apt-get install -y libapr1-dev libaprutil1-dev - name: Install Build Wrapper - uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v4.2.1 + uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5.3.1 env: SONAR_HOST_URL: ${{ env.SONAR_SERVER_URL }} @@ -84,7 +84,7 @@ jobs: -o "$BaseDir/build/coverage.xml" - name: SonarQube Scan - uses: SonarSource/sonarqube-scan-action@v4.2.1 + uses: SonarSource/sonarqube-scan-action@v5.3.1 env: SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} SONAR_HOST_URL: ${{ env.SONAR_SERVER_URL }} diff --git a/src/main/cpp/charsetdecoder.cpp b/src/main/cpp/charsetdecoder.cpp index b985f475..ed79d440 100644 --- a/src/main/cpp/charsetdecoder.cpp +++ b/src/main/cpp/charsetdecoder.cpp @@ -15,6 +15,7 @@ * limitations under the License. */ #define NOMINMAX /* tell windows not to define min/max macros */ +#include <log4cxx/private/string_c11.h> #include <log4cxx/logstring.h> #include <log4cxx/helpers/charsetdecoder.h> #include <log4cxx/helpers/bytebuffer.h> @@ -585,6 +586,12 @@ CharsetDecoderPtr CharsetDecoder::getDecoder(const LogString& charset) #endif } +log4cxx_status_t CharsetDecoder::decode(const char* in, size_t maxByteCount, LogString& out) +{ + ByteBuffer buf((char*)in, strnlen_s(in, maxByteCount)); + return decode(buf, out); +} + diff --git a/src/main/cpp/defaultconfigurator.cpp b/src/main/cpp/defaultconfigurator.cpp index fe19df32..c34f3d64 100644 --- a/src/main/cpp/defaultconfigurator.cpp +++ b/src/main/cpp/defaultconfigurator.cpp @@ -214,7 +214,6 @@ DefaultConfigurator::configureFromFile(const std::vector<LogString>& directories std::get<0>(result) = ConfigurationStatus::Configured; return result; } - LogLog::warn(LOG4CXX_STR("Unable to load: ") + candidate_str); } } } diff --git a/src/main/cpp/domconfigurator.cpp b/src/main/cpp/domconfigurator.cpp index 6f78b3ac..7c940858 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/private/string_c11.h> #include <log4cxx/logstring.h> #include <log4cxx/xml/domconfigurator.h> #include <log4cxx/appender.h> @@ -68,6 +67,7 @@ struct DOMConfigurator::DOMConfiguratorPrivate helpers::Properties props = Configurator::properties(); spi::LoggerRepositoryPtr repository; spi::LoggerFactoryPtr loggerFactory; + bool appenderAdded{ false }; }; namespace LOG4CXX_NS @@ -190,9 +190,19 @@ AppenderPtr DOMConfigurator::findAppenderByReference( apr_xml_doc* doc, AppenderMap& appenders) { + AppenderPtr appender; LogString appenderName(subst(getAttribute(utf8Decoder, appenderRef, REF_ATTR))); + if (appenderName.empty()) + { + LogString msg(LOG4CXX_STR("[")); + utf8Decoder->decode(appenderRef->name, MAX_ATTRIBUTE_NAME_LEN, msg); + msg += LOG4CXX_STR("] attribute ["); + utf8Decoder->decode(REF_ATTR, MAX_ATTRIBUTE_NAME_LEN, msg); + msg += LOG4CXX_STR("] not found"); + LogLog::warn(msg); + return appender; + } AppenderMap::const_iterator match = appenders.find(appenderName); - AppenderPtr appender; if (match != appenders.end()) { @@ -311,27 +321,23 @@ AppenderPtr DOMConfigurator::parseAppender(Pool& p, } else if (tagName == APPENDER_REF_TAG) { - LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR)); - - if (!refName.empty() && appender->instanceof(AppenderAttachable::getStaticClass())) + if (appender->instanceof(AppenderAttachable::getStaticClass())) { AppenderAttachablePtr aa = LOG4CXX_NS::cast<AppenderAttachable>(appender); - if (LogLog::isDebugEnabled()) + if (auto delegateAppender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders)) { - LogLog::debug(LOG4CXX_STR("Attaching ") + Appender::getStaticClass().getName() - + LOG4CXX_STR(" named [") + refName + LOG4CXX_STR("] to ") + Appender::getStaticClass().getName() - + LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]")); + if (LogLog::isDebugEnabled()) + { + LogLog::debug(LOG4CXX_STR("Attaching ") + Appender::getStaticClass().getName() + + LOG4CXX_STR(" named [") + delegateAppender->getName() + LOG4CXX_STR("] to ") + Appender::getStaticClass().getName() + + LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]")); + } + aa->addAppender(delegateAppender); } - aa->addAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders)); - } - else if (refName.empty()) - { - LogLog::error(LOG4CXX_STR("Can't add ") + Appender::getStaticClass().getName() + LOG4CXX_STR(" with empty ref attribute")); } else { - LogLog::error(LOG4CXX_STR("Requesting attachment of ") + Appender::getStaticClass().getName() - + LOG4CXX_STR(" named [") + refName + LOG4CXX_STR("] to ") + Appender::getStaticClass().getName() + LogLog::error(LOG4CXX_STR("Cannot attach to ") + Appender::getStaticClass().getName() + LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]") + LOG4CXX_STR(" which does not implement ") + AppenderAttachable::getStaticClass().getName()); } @@ -386,7 +392,8 @@ void DOMConfigurator::parseErrorHandler(Pool& p, } else if (tagName == APPENDER_REF_TAG) { - eh->setBackupAppender(findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders)); + if (auto appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders)) + eh->setBackupAppender(appender); } else if (tagName == LOGGER_REF) { @@ -461,7 +468,7 @@ void DOMConfigurator::parseLogger( if (LogLog::isDebugEnabled()) { - LogLog::debug(LOG4CXX_STR("Retreiving an instance of ") + loggerName); + LogLog::debug(LOG4CXX_STR("Getting [") + loggerName + LOG4CXX_STR("]")); } LoggerPtr logger = m_priv->repository->getLogger(loggerName, m_priv->loggerFactory); @@ -493,7 +500,12 @@ void DOMConfigurator::parseLoggerFactory( if (className.empty()) { - LogLog::error(LOG4CXX_STR("Logger Factory tag class attribute not found.")); + LogString msg(LOG4CXX_STR("[")); + utf8Decoder->decode(factoryElement->name, MAX_ATTRIBUTE_NAME_LEN, msg); + msg += LOG4CXX_STR("] attribute ["); + utf8Decoder->decode(CLASS_ATTR, MAX_ATTRIBUTE_NAME_LEN, msg); + msg += LOG4CXX_STR("] not found"); + LogLog::warn(msg); } else { @@ -558,25 +570,16 @@ void DOMConfigurator::parseChildrenOfLoggerElement( if (tagName == APPENDER_REF_TAG) { - AppenderPtr appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders); - LogString refName = subst(getAttribute(utf8Decoder, currentElement, REF_ATTR)); - - if (appender) + if (auto appender = findAppenderByReference(p, utf8Decoder, currentElement, doc, appenders)) { if (LogLog::isDebugEnabled()) { LogLog::debug(LOG4CXX_STR("Adding ") + Appender::getStaticClass().getName() - + LOG4CXX_STR(" named [") + refName + LOG4CXX_STR("]") + + LOG4CXX_STR(" named [") + appender->getName() + LOG4CXX_STR("]") + LOG4CXX_STR(" to logger [") + logger->getName() + LOG4CXX_STR("]")); } newappenders.push_back(appender); } - else - { - LogLog::debug(LOG4CXX_STR("Appender named [") + refName + - LOG4CXX_STR("] not found.")); - } - } else if (tagName == LEVEL_TAG) { @@ -594,8 +597,10 @@ void DOMConfigurator::parseChildrenOfLoggerElement( if (newappenders.empty()) logger->removeAllAppenders(); else + { logger->replaceAppenders(newappenders); - + m_priv->appenderAdded = true; + } propSetter.activate(p); } @@ -760,7 +765,7 @@ void DOMConfigurator::parseLevel( LogString levelStr(subst(getAttribute(utf8Decoder, element, VALUE_ATTR))); if (LogLog::isDebugEnabled()) { - LogLog::debug(LOG4CXX_STR("Level value for ") + loggerName + LOG4CXX_STR(" is [") + levelStr + LOG4CXX_STR("]")); + LogLog::debug(LOG4CXX_STR("Setting [") + loggerName + LOG4CXX_STR("] level to [") + levelStr + LOG4CXX_STR("]")); } if (StringHelper::equalsIgnoreCase(levelStr, LOG4CXX_STR("INHERITED"), LOG4CXX_STR("inherited")) @@ -815,7 +820,7 @@ void DOMConfigurator::parseLevel( if (LogLog::isDebugEnabled()) { - LogLog::debug(loggerName + LOG4CXX_STR(" level set to ") + + LogLog::debug(LOG4CXX_STR("[") + loggerName + LOG4CXX_STR("] level is ") + logger->getEffectiveLevel()->toString()); } } @@ -841,7 +846,6 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure ) { m_priv->repository = repository ? repository : LogManager::getLoggerRepository(); - m_priv->repository->setConfigured(true); #if LOG4CXX_ABI_VERSION <= 15 m_priv->loggerFactory = std::make_shared<DefaultLoggerFactory>(); @@ -856,15 +860,9 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure if (rv != APR_SUCCESS) { - // There is not technically an exception thrown here, but this behavior matches - // what the PropertyConfigurator does - IOException io(rv); - LogString msg2(LOG4CXX_STR("Could not read configuration file [")); - msg2.append(filename.getPath()); - msg2.append(LOG4CXX_STR("]. ")); - LOG4CXX_DECODE_CHAR(msg, io.what()); - msg2.append(msg); - LogLog::error(msg2); + LogLog::error(LOG4CXX_STR("Could not open configuration file [") + + filename.getPath() + LOG4CXX_STR("]") + , IOException(rv)); return spi::ConfigurationStatus::NotConfigured; } else @@ -874,32 +872,32 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure if (LogLog::isDebugEnabled()) { - LogString debugMsg = LOG4CXX_STR("Loading configuration file [") - + filename.getPath() + LOG4CXX_STR("]"); - LogLog::debug(debugMsg); + LogLog::debug(LOG4CXX_STR("Loading configuration file [") + + filename.getPath() + LOG4CXX_STR("]")); } 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); - + LogString reason; if (parser) { - apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)); - LOG4CXX_DECODE_CHAR(lerrbufXML, std::string(errbufXML)); - msg2.append(lerrbufXML); + char errbuf[2000]; + apr_xml_parser_geterror(parser, errbuf, sizeof(errbuf)); + LOG4CXX_DECODE_CHAR(lsErrbuf, std::string(errbuf)); + reason.append(lsErrbuf); } - - LogLog::error(msg2); + else + { + char errbuf[2000]; + apr_strerror(rv, errbuf, sizeof(errbuf)); + LOG4CXX_DECODE_CHAR(lsErrbuf, std::string(errbuf)); + reason.append(lsErrbuf); + } + LogLog::error(LOG4CXX_STR("Error parsing file [") + + filename.getPath() + LOG4CXX_STR("]") + , RuntimeException(reason)); return spi::ConfigurationStatus::NotConfigured; } else @@ -910,6 +908,15 @@ spi::ConfigurationStatus DOMConfigurator::doConfigure } } + if (!m_priv->appenderAdded) + { + LogLog::warn(LOG4CXX_STR("[") + filename.getPath() + + LOG4CXX_STR("] did not add an ") + Appender::getStaticClass().getName() + + LOG4CXX_STR(" to a logger")); + return spi::ConfigurationStatus::NotConfigured; + } + + m_priv->repository->setConfigured(true); return spi::ConfigurationStatus::Configured; } @@ -1042,7 +1049,12 @@ void DOMConfigurator::parse( } else { - LogLog::error(LOG4CXX_STR("DOM element is - not a <configuration> element.")); + LogString msg(LOG4CXX_STR("Root element [")); + utf8Decoder->decode(element->name, MAX_ATTRIBUTE_NAME_LEN, msg); + msg += LOG4CXX_STR("] is not ["); + utf8Decoder->decode(CONFIGURATION_TAG, MAX_ATTRIBUTE_NAME_LEN, msg); + msg += LOG4CXX_STR("]"); + LogLog::error(msg); return; } } @@ -1163,8 +1175,7 @@ LogString DOMConfigurator::getAttribute( { if (attrName == attr->name) { - ByteBuffer buf((char*) attr->value, strnlen_s(attr->value, MAX_ATTRIBUTE_NAME_LEN)); - utf8Decoder->decode(buf, attrValue); + utf8Decoder->decode(attr->value, MAX_ATTRIBUTE_NAME_LEN, attrValue); } } diff --git a/src/main/cpp/propertyconfigurator.cpp b/src/main/cpp/propertyconfigurator.cpp index 6dd2036b..b1c1d939 100644 --- a/src/main/cpp/propertyconfigurator.cpp +++ b/src/main/cpp/propertyconfigurator.cpp @@ -86,19 +86,44 @@ class PropertyWatchdog : public FileWatchdog IMPLEMENT_LOG4CXX_OBJECT(PropertyConfigurator) +using RegistryType = std::map<LogString, AppenderPtr>; +using RegistryPtr = std::unique_ptr<RegistryType>; + +#if 15 < LOG4CXX_ABI_VERSION +struct PropertyConfigurator::PrivateData +{ + + /** + Used internally to keep track of configured appenders. + */ + RegistryPtr registry{ std::make_unique<RegistryType>() }; + + /** + Used to create new instances of logger + */ + spi::LoggerFactoryPtr loggerFactory{ std::make_shared<LoggerFactory>() }; + + /** + True if an appender was added to a logger + */ + bool appenderAdded{ false }; +}; +PropertyConfigurator::PropertyConfigurator() + : m_priv{ std::make_unique<PrivateData>() } +#else +#define m_priv this PropertyConfigurator::PropertyConfigurator() : registry(new std::map<LogString, AppenderPtr>()) -#if LOG4CXX_ABI_VERSION <= 15 , loggerFactory(new DefaultLoggerFactory()) -#else - , loggerFactory(new LoggerFactory()) #endif { } PropertyConfigurator::~PropertyConfigurator() { +#if LOG4CXX_ABI_VERSION <= 15 delete registry; +#endif } spi::ConfigurationStatus PropertyConfigurator::doConfigure @@ -110,11 +135,13 @@ spi::ConfigurationStatus PropertyConfigurator::doConfigure #endif ) { - auto hierarchy = repository ? repository : LogManager::getLoggerRepository(); - hierarchy->setConfigured(true); - + auto result = spi::ConfigurationStatus::NotConfigured; + if (LogLog::isDebugEnabled()) + { + LogLog::debug(LOG4CXX_STR("Loading configuration file [") + + configFileName.getPath() + LOG4CXX_STR("]")); + } Properties props = Configurator::properties(); - try { InputStreamPtr inputStream = InputStreamPtr( new FileInputStream(configFileName) ); @@ -122,29 +149,32 @@ spi::ConfigurationStatus PropertyConfigurator::doConfigure } catch (const IOException& ex) { - LOG4CXX_DECODE_CHAR(lsMsg, ex.what()); - LogLog::error(((LogString) LOG4CXX_STR("Could not read configuration file [")) - + configFileName.getPath() + LOG4CXX_STR("]: ") + lsMsg); - return spi::ConfigurationStatus::NotConfigured; + LogLog::error(LOG4CXX_STR("Could not load properties from [") + + configFileName.getPath() + LOG4CXX_STR("]"), ex); + return result; } try { - if (LogLog::isDebugEnabled()) + result = doConfigure(props, repository ? repository : LogManager::getLoggerRepository()); +#if LOG4CXX_ABI_VERSION <= 15 + if (m_priv->registry->empty()) +#else + if (!m_priv->appenderAdded) +#endif { - LogString debugMsg = LOG4CXX_STR("Loading configuration file [") - + configFileName.getPath() + LOG4CXX_STR("]"); - LogLog::debug(debugMsg); + LogLog::warn(LOG4CXX_STR("[") + configFileName.getPath() + + LOG4CXX_STR("] did not add an ") + Appender::getStaticClass().getName() + + LOG4CXX_STR(" to a logger")); } - return doConfigure(props, hierarchy); } catch (const std::exception& ex) { - LogLog::error(((LogString) LOG4CXX_STR("Could not parse configuration file [")) + LogLog::error(LOG4CXX_STR("Exception thrown processing [") + configFileName.getPath() + LOG4CXX_STR("]: "), ex); } - return spi::ConfigurationStatus::NotConfigured; + return result; } spi::ConfigurationStatus PropertyConfigurator::configure(const File& configFilename) @@ -175,8 +205,6 @@ spi::ConfigurationStatus PropertyConfigurator::configureAndWatch( spi::ConfigurationStatus PropertyConfigurator::doConfigure(helpers::Properties& properties, spi::LoggerRepositoryPtr hierarchy) { - hierarchy->setConfigured(true); - LogString debugValue(properties.getProperty(LOG4CXX_STR("log4j.debug"))); if (!debugValue.empty()) { @@ -225,14 +253,18 @@ spi::ConfigurationStatus PropertyConfigurator::doConfigure(helpers::Properties& configureRootLogger(properties, hierarchy); configureLoggerFactory(properties); parseCatsAndRenderers(properties, hierarchy); - LogLog::debug(LOG4CXX_STR("Finished configuring.")); +#if LOG4CXX_ABI_VERSION <= 15 + auto result = m_priv->registry->empty() +#else + auto result = !m_priv->appenderAdded +#endif + ? spi::ConfigurationStatus::NotConfigured + : spi::ConfigurationStatus::Configured; - // We don't want to hold references to appenders preventing their - // destruction. - registry->clear(); - - return spi::ConfigurationStatus::Configured; + if (spi::ConfigurationStatus::Configured == result) + hierarchy->setConfigured(true); + return result; } void PropertyConfigurator::configureLoggerFactory(helpers::Properties& props) @@ -252,9 +284,9 @@ void PropertyConfigurator::configureLoggerFactory(helpers::Properties& props) #endif ); - loggerFactory = LOG4CXX_NS::cast<LoggerFactory>( instance ); + m_priv->loggerFactory = LOG4CXX_NS::cast<LoggerFactory>( instance ); Pool p; - PropertySetter::setProperties(loggerFactory, props, LOG4CXX_STR("log4j.factory."), p); + PropertySetter::setProperties(m_priv->loggerFactory, props, LOG4CXX_STR("log4j.factory."), p); } } @@ -296,7 +328,7 @@ void PropertyConfigurator::parseCatsAndRenderers(helpers::Properties& props, ).length(); auto loggerName = key.substr(prefixLength); auto value = OptionConverter::findAndSubst(key, props); - auto logger = hierarchy->getLogger(loggerName, loggerFactory); + auto logger = hierarchy->getLogger(loggerName, m_priv->loggerFactory); auto additivity = parseAdditivityForLogger(props, logger, loggerName); parseLogger(props, logger, key, loggerName, value, additivity); @@ -406,7 +438,10 @@ void PropertyConfigurator::parseLogger( newappenders.push_back(appender); } } - +#if 15 < LOG4CXX_ABI_VERSION + if (!newappenders.empty()) + m_priv->appenderAdded = true; +#endif logger->reconfigure( newappenders, additivity ); } @@ -545,10 +580,10 @@ AppenderPtr PropertyConfigurator::parseAppender( void PropertyConfigurator::registryPut(const AppenderPtr& appender) { - (*registry)[appender->getName()] = appender; + (*m_priv->registry)[appender->getName()] = appender; } AppenderPtr PropertyConfigurator::registryGet(const LogString& name) { - return (*registry)[name]; + return (*m_priv->registry)[name]; } diff --git a/src/main/include/log4cxx/helpers/charsetdecoder.h b/src/main/include/log4cxx/helpers/charsetdecoder.h index 3c276ac8..d801e70b 100644 --- a/src/main/include/log4cxx/helpers/charsetdecoder.h +++ b/src/main/include/log4cxx/helpers/charsetdecoder.h @@ -77,14 +77,24 @@ class LOG4CXX_EXPORT CharsetDecoder : public Object /** - * Decodes as many bytes as possible from the given - * input buffer, writing the results to the given output string. - * @param in input buffer. - * @param out output string. + * Decodes as many bytes as possible from \c in, + * appending the result onto \c out. + * @param in a null terminated string. + * @param out the string onto which characters are appended. * @return APR_SUCCESS if not encoding errors were found. */ - virtual log4cxx_status_t decode(ByteBuffer& in, - LogString& out) = 0; + virtual log4cxx_status_t decode(ByteBuffer& in, LogString& out) = 0; + + + /** + * Decodes up to \c maxByteCount bytes from \c in, + * appending the result onto \c out. + * @param in a null terminated string. + * @param maxByteCount the limit on the size of \c in. + * @param out the string onto which characters are appended. + * @return APR_SUCCESS if not encoding errors were found. + */ + log4cxx_status_t decode(const char* in, size_t maxByteCount, LogString& out); /** * Determins if status value indicates an invalid byte sequence. diff --git a/src/main/include/log4cxx/propertyconfigurator.h b/src/main/include/log4cxx/propertyconfigurator.h index b5e5872b..eac2aba4 100644 --- a/src/main/include/log4cxx/propertyconfigurator.h +++ b/src/main/include/log4cxx/propertyconfigurator.h @@ -249,6 +249,11 @@ class LOG4CXX_EXPORT PropertyConfigurator : virtual public spi::Configurator, virtual public helpers::Object { +#if 15 < LOG4CXX_ABI_VERSION + private: + struct PrivateData; + LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(PrivateData, m_priv) +#else protected: /** @@ -260,7 +265,7 @@ class LOG4CXX_EXPORT PropertyConfigurator : Used to create new instances of logger */ LOG4CXX_DECLARE_PRIVATE_MEMBER(spi::LoggerFactoryPtr, loggerFactory) - +#endif public: DECLARE_LOG4CXX_OBJECT(PropertyConfigurator) BEGIN_LOG4CXX_CAST_MAP() diff --git a/src/test/cpp/asyncappendertestcase.cpp b/src/test/cpp/asyncappendertestcase.cpp index ea6781fc..206efc1f 100644 --- a/src/test/cpp/asyncappendertestcase.cpp +++ b/src/test/cpp/asyncappendertestcase.cpp @@ -360,7 +360,8 @@ class AsyncAppenderTestCase : public AppenderSkeletonTestCase #if LOG4CXX_HAS_DOMCONFIGURATOR void testConfiguration() { - log4cxx::xml::DOMConfigurator::configure("input/xml/asyncAppender1.xml"); + auto status = xml::DOMConfigurator::configure("input/xml/asyncAppender1.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); AsyncAppenderPtr asyncAppender = log4cxx::cast<AsyncAppender>(Logger::getRootLogger()->getAppender(LOG4CXX_STR("ASYNC"))); LOGUNIT_ASSERT(!(asyncAppender == 0)); LOGUNIT_ASSERT_EQUAL(100, asyncAppender->getBufferSize()); diff --git a/src/test/cpp/customlogger/xloggertestcase.cpp b/src/test/cpp/customlogger/xloggertestcase.cpp index 74302e5c..7a4ef690 100644 --- a/src/test/cpp/customlogger/xloggertestcase.cpp +++ b/src/test/cpp/customlogger/xloggertestcase.cpp @@ -74,7 +74,8 @@ public: std::string fn("input/xml/customLogger"); fn.append(number); fn.append(".xml"); - DOMConfigurator::configure(fn); + auto status = DOMConfigurator::configure(fn); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); int i = 0; LOG4CXX_LOG(logger, log4cxx::XLevel::getTrace(), "Message " << i); diff --git a/src/test/cpp/db/odbcappendertestcase.cpp b/src/test/cpp/db/odbcappendertestcase.cpp index ca568aed..2e7dec99 100644 --- a/src/test/cpp/db/odbcappendertestcase.cpp +++ b/src/test/cpp/db/odbcappendertestcase.cpp @@ -84,7 +84,8 @@ class ODBCAppenderTestCase : public AppenderSkeletonTestCase // void testConnectUsingDSN() { - xml::DOMConfigurator::configure("input/xml/odbcAppenderDSN-Log4cxxTest.xml"); + auto status = xml::DOMConfigurator::configure("input/xml/odbcAppenderDSN-Log4cxxTest.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); auto odbc = Logger::getLogger("DB.UnitTest"); for (int i = 0; i < 100; ++i) { diff --git a/src/test/cpp/fmttest.cpp b/src/test/cpp/fmttest.cpp index 3827f69c..c7674d70 100644 --- a/src/test/cpp/fmttest.cpp +++ b/src/test/cpp/fmttest.cpp @@ -85,21 +85,24 @@ public: void test1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/fmtLayout1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/fmtLayout1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.1"))); } void test1_expanded() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/fmtLayout1_expanded.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/fmtLayout1_expanded.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.1"))); } void test10() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/fmtLayout10.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/fmtLayout10.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; diff --git a/src/test/cpp/helpers/messagebuffertest.cpp b/src/test/cpp/helpers/messagebuffertest.cpp index f953ea30..e257528d 100644 --- a/src/test/cpp/helpers/messagebuffertest.cpp +++ b/src/test/cpp/helpers/messagebuffertest.cpp @@ -148,7 +148,8 @@ public: root = Logger::getRootLogger(); logger = Logger::getLogger(LOG4CXX_STR("java.org.apache.log4j.PatternLayoutTest")); - PropertyConfigurator::configure(LOG4CXX_FILE("input/messagebuffer1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/messagebuffer1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); int num = 220; LOG4CXX_INFO(logger, "number in hex: " << std::hex << num); diff --git a/src/test/cpp/hierarchythresholdtestcase.cpp b/src/test/cpp/hierarchythresholdtestcase.cpp index de836f09..65383cd8 100644 --- a/src/test/cpp/hierarchythresholdtestcase.cpp +++ b/src/test/cpp/hierarchythresholdtestcase.cpp @@ -59,56 +59,64 @@ public: void test1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.1"))); } void test2() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold2.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold2.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.2"))); } void test3() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold3.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold3.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.3"))); } void test4() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold4.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold4.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.4"))); } void test5() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold5.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold5.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.5"))); } void test6() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold6.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold6.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.6"))); } void test7() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold7.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold7.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.7"))); } void test8() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold8.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/hierarchyThreshold8.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/hierarchyThreshold.8"))); } diff --git a/src/test/cpp/l7dtestcase.cpp b/src/test/cpp/l7dtestcase.cpp index 7c70b74a..36b5eea8 100644 --- a/src/test/cpp/l7dtestcase.cpp +++ b/src/test/cpp/l7dtestcase.cpp @@ -77,7 +77,8 @@ public: void test1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/l7d1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/l7d1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); log4cxx::helpers::Pool pool; diff --git a/src/test/cpp/locationdisabledtest.cpp b/src/test/cpp/locationdisabledtest.cpp index fa682f61..976e4d81 100644 --- a/src/test/cpp/locationdisabledtest.cpp +++ b/src/test/cpp/locationdisabledtest.cpp @@ -48,7 +48,8 @@ public: void test1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/locationdisabled.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/locationdisabled.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(LOG4CXX_STR("output/location-disabled-test"), LOG4CXX_FILE("witness/location1-disabled"))); } diff --git a/src/test/cpp/locationtest.cpp b/src/test/cpp/locationtest.cpp index aa98a63d..701e1896 100644 --- a/src/test/cpp/locationtest.cpp +++ b/src/test/cpp/locationtest.cpp @@ -48,7 +48,8 @@ public: void test1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/location1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/location1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(LOG4CXX_STR("output/location-good-test"), LOG4CXX_FILE("witness/location1-good"))); } diff --git a/src/test/cpp/ndctestcase.cpp b/src/test/cpp/ndctestcase.cpp index 75e55371..383f7a71 100644 --- a/src/test/cpp/ndctestcase.cpp +++ b/src/test/cpp/ndctestcase.cpp @@ -68,7 +68,8 @@ public: void test1() { - PropertyConfigurator::configure(File("input/ndc/NDC1.properties")); + auto status = PropertyConfigurator::configure(File("input/ndc/NDC1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, File("witness/ndc/NDC.1"))); } diff --git a/src/test/cpp/net/smtpappendertestcase.cpp b/src/test/cpp/net/smtpappendertestcase.cpp index 213cf4f3..d3036239 100644 --- a/src/test/cpp/net/smtpappendertestcase.cpp +++ b/src/test/cpp/net/smtpappendertestcase.cpp @@ -106,7 +106,8 @@ class SMTPAppenderTestCase : public AppenderSkeletonTestCase */ void testTrigger() { - xml::DOMConfigurator::configure("input/xml/smtpAppender1.xml"); + auto status = xml::DOMConfigurator::configure("input/xml/smtpAppender1.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); auto appender = log4cxx::cast<SMTPAppender>(Logger::getRootLogger()->getAppender(LOG4CXX_STR("A1"))); LOGUNIT_ASSERT(appender); auto evaluator = appender->getEvaluator(); @@ -135,7 +136,8 @@ class SMTPAppenderTestCase : public AppenderSkeletonTestCase void testValid() { - xml::DOMConfigurator::configure("input/xml/smtpAppenderValid.xml"); + auto status = xml::DOMConfigurator::configure("input/xml/smtpAppenderValid.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); auto root = Logger::getRootLogger(); LOG4CXX_INFO(root, "Hello, World.\n\nThis paragraph should be preceeded by a blank line."); diff --git a/src/test/cpp/net/xmlsocketappendertestcase.cpp b/src/test/cpp/net/xmlsocketappendertestcase.cpp index cfd715b8..95b450e7 100644 --- a/src/test/cpp/net/xmlsocketappendertestcase.cpp +++ b/src/test/cpp/net/xmlsocketappendertestcase.cpp @@ -48,7 +48,8 @@ class XMLSocketAppenderTestCase : public AppenderSkeletonTestCase void test_fluent_bit() { - xml::DOMConfigurator::configure("input/xml/fluent-bit.xml"); + auto status = xml::DOMConfigurator::configure("input/xml/fluent-bit.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); auto log = Logger::getRootLogger(); for (int i = 0; i < 100; ++i) { diff --git a/src/test/cpp/patternlayouttest.cpp b/src/test/cpp/patternlayouttest.cpp index a5723bbf..c142ae04 100644 --- a/src/test/cpp/patternlayouttest.cpp +++ b/src/test/cpp/patternlayouttest.cpp @@ -105,14 +105,16 @@ public: void test1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.1"))); } void test2() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout2.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout2.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -140,7 +142,8 @@ public: void test3() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout3.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout3.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -170,7 +173,8 @@ public: // 06 avr. 2002 18:30:58,937 [12345] DEBUG atternLayoutTest - Message 0 void test4() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout4.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout4.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -198,7 +202,8 @@ public: void test5() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout5.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout5.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -226,7 +231,8 @@ public: void test6() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout6.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout6.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -254,7 +260,8 @@ public: void test7() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout7.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout7.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -282,7 +289,8 @@ public: void test8() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout8.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout8.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); @@ -313,7 +321,8 @@ public: void test9() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout9.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout9.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -339,7 +348,8 @@ public: void test10() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout10.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout10.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -371,7 +381,8 @@ public: void test11() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout11.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout11.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -397,7 +408,8 @@ public: void test12() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout12.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout12.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter filter1; @@ -427,21 +439,24 @@ public: void test13() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout13.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout13.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.13"))); } void test14() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout14.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout14.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); LOGUNIT_ASSERT(Compare::compare(TEMP, LOG4CXX_FILE("witness/patternLayout.14"))); } void testMDC1() { - PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout.mdc.1.properties")); + auto status = PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout.mdc.1.properties")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); MDC::put(LOG4CXX_TEST_STR("key1"), LOG4CXX_TEST_STR("va11")); MDC::put(LOG4CXX_TEST_STR("key2"), LOG4CXX_TEST_STR("va12")); logger->debug(LOG4CXX_TEST_STR("Hello World")); diff --git a/src/test/cpp/propertyconfiguratortest.cpp b/src/test/cpp/propertyconfiguratortest.cpp index b051614e..2d57ee67 100644 --- a/src/test/cpp/propertyconfiguratortest.cpp +++ b/src/test/cpp/propertyconfiguratortest.cpp @@ -41,7 +41,8 @@ public: props.put(LOG4CXX_STR("log4j.logger.org.apache.log4j.PropertyConfiguratorTest"), LOG4CXX_STR("inherited,VECTOR2")); props.put(LOG4CXX_STR("log4j.appender.VECTOR1"), LOG4CXX_STR("org.apache.log4j.VectorAppender")); props.put(LOG4CXX_STR("log4j.appender.VECTOR2"), LOG4CXX_STR("org.apache.log4j.VectorAppender")); - PropertyConfigurator::configure(props); + auto status = PropertyConfigurator::configure(props); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); LoggerPtr logger = Logger::getLogger("org.apache.log4j.PropertyConfiguratorTest"); LOGUNIT_ASSERT_EQUAL((int) Level::DEBUG_INT, logger->getEffectiveLevel()->toInt()); @@ -58,7 +59,8 @@ public: props.put(LOG4CXX_STR("log4j.logger.org.apache.log4j.PropertyConfiguratorTest"), LOG4CXX_STR("NuLL,VECTOR2")); props.put(LOG4CXX_STR("log4j.appender.VECTOR1"), LOG4CXX_STR("org.apache.log4j.VectorAppender")); props.put(LOG4CXX_STR("log4j.appender.VECTOR2"), LOG4CXX_STR("org.apache.log4j.VectorAppender")); - PropertyConfigurator::configure(props); + auto status = PropertyConfigurator::configure(props); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); LoggerPtr logger = Logger::getLogger("org.apache.log4j.PropertyConfiguratorTest"); LOGUNIT_ASSERT_EQUAL((int) Level::DEBUG_INT, logger->getEffectiveLevel()->toInt()); @@ -74,7 +76,8 @@ public: props.put(LOG4CXX_STR("log4j.rootLogger"), LOG4CXX_STR("ALL,VECTOR1")); props.put(LOG4CXX_STR("log4j.appender.VECTOR1"), LOG4CXX_STR("org.apache.log4j.VectorAppender")); props.put(LOG4CXX_STR("log4j.appender.VECTOR1.threshold"), LOG4CXX_STR("WARN")); - PropertyConfigurator::configure(props); + auto status = PropertyConfigurator::configure(props); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); LoggerPtr root(Logger::getRootLogger()); VectorAppenderPtr appender = log4cxx::cast<VectorAppender>(root->getAppender(LOG4CXX_STR("VECTOR1"))); LOGUNIT_ASSERT_EQUAL((int) Level::WARN_INT, appender->getThreshold()->toInt()); diff --git a/src/test/cpp/rolling/filterbasedrollingtest.cpp b/src/test/cpp/rolling/filterbasedrollingtest.cpp index 43448125..bbff3fdc 100644 --- a/src/test/cpp/rolling/filterbasedrollingtest.cpp +++ b/src/test/cpp/rolling/filterbasedrollingtest.cpp @@ -60,9 +60,8 @@ public: void test1() { #if LOG4CXX_HAS_DOMCONFIGURATOR - log4cxx::xml::DOMConfigurator::configure( - "./input/rolling/filter1.xml" /*, LogManager::getLoggerRepository() */); - + auto status = xml::DOMConfigurator::configure("./input/rolling/filter1.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(LOG4CXX_STR("output/filterBased-test1")); #endif } diff --git a/src/test/cpp/varia/errorhandlertestcase.cpp b/src/test/cpp/varia/errorhandlertestcase.cpp index 468ab4bf..5a479258 100644 --- a/src/test/cpp/varia/errorhandlertestcase.cpp +++ b/src/test/cpp/varia/errorhandlertestcase.cpp @@ -85,7 +85,8 @@ public: void test1() { - DOMConfigurator::configure("input/xml/fallback1.xml"); + auto status = DOMConfigurator::configure("input/xml/fallback1.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); auto appender = root->getAppender(LOG4CXX_STR("PRIMARY")); auto primary = log4cxx::cast<FileAppender>(appender); auto errHandle = primary->getErrorHandler(); @@ -127,7 +128,8 @@ public: void test2() { - DOMConfigurator::configure("input/xml/fallback2.xml"); + auto status = DOMConfigurator::configure("input/xml/fallback2.xml"); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); auto appender = root->getAppender(LOG4CXX_STR("PRIMARY")); auto primary = log4cxx::cast<FileAppender>(appender); auto errHandle = primary->getErrorHandler(); diff --git a/src/test/cpp/xml/customleveltestcase.cpp b/src/test/cpp/xml/customleveltestcase.cpp index d2259a56..b58c0081 100644 --- a/src/test/cpp/xml/customleveltestcase.cpp +++ b/src/test/cpp/xml/customleveltestcase.cpp @@ -69,7 +69,8 @@ public: void test1() { - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel1.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel1.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); const File witness("witness/customLevel.1"); LOGUNIT_ASSERT(Compare::compare(TEMP, witness)); @@ -77,7 +78,8 @@ public: void test2() { - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel2.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel2.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); const File witness("witness/customLevel.2"); LOGUNIT_ASSERT(Compare::compare(TEMP, witness)); @@ -86,6 +88,7 @@ public: void test3() { DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel3.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); const File witness("witness/customLevel.3"); LOGUNIT_ASSERT(Compare::compare(TEMP, witness)); @@ -93,7 +96,8 @@ public: void test4() { - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel4.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/customLevel4.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); const File witness("witness/customLevel.4"); LOGUNIT_ASSERT(Compare::compare(TEMP, witness)); diff --git a/src/test/cpp/xml/domtestcase.cpp b/src/test/cpp/xml/domtestcase.cpp index 5f98b29e..b94ab641 100644 --- a/src/test/cpp/xml/domtestcase.cpp +++ b/src/test/cpp/xml/domtestcase.cpp @@ -17,6 +17,7 @@ #include <log4cxx/logger.h> #include <log4cxx/xml/domconfigurator.h> +#include <log4cxx/defaultconfigurator.h> #include "../logunit.h" #include "../util/compare.h" #include "xlevel.h" @@ -56,6 +57,7 @@ LOGUNIT_CLASS(DOMTestCase) LOGUNIT_TEST(recursiveAppenderRef); LOGUNIT_TEST(invalidAppender); LOGUNIT_TEST(invalidLevel); + LOGUNIT_TEST(testAutoFallback); LOGUNIT_TEST_SUITE_END(); LoggerPtr root; @@ -73,6 +75,7 @@ LOGUNIT_CLASS(DOMTestCase) public: void setUp() { + LogLog::setInternalDebugging(true); root = Logger::getRootLogger(); logger = Logger::getLogger(LOG4CXX_TEST_STR("org.apache.log4j.xml.DOMTestCase")); } @@ -89,8 +92,8 @@ public: void test1() { - LogLog::setInternalDebugging(true); - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase1.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase1.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ControlFilter cf1; @@ -134,7 +137,8 @@ public: // void test2() { - DOMConfigurator::configure(LOG4CXX_TEST_STR("input\\xml\\DOMTestCase2.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input\\xml\\DOMTestCase2.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); common(); ThreadFilter threadFilter; @@ -196,7 +200,8 @@ public: */ void test3() { - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase3.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase3.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); LOG4CXX_INFO(logger, "File name is expected to end with a superscript 3"); #if LOG4CXX_LOGCHAR_IS_UTF8 const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, static_cast<logchar>(0xC2), static_cast<logchar>(0xB3), 0 }; @@ -216,7 +221,8 @@ public: */ void test4() { - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase4.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMTestCase4.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); LOG4CXX_INFO(logger, "File name is expected to end with an ideographic 4"); #if LOG4CXX_LOGCHAR_IS_UTF8 const logchar fname[] = { 0x6F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2F, 0x64, 0x6F, 0x6D, static_cast<logchar>(0xE3), static_cast<logchar>(0x86), static_cast<logchar>(0x95), 0 }; @@ -234,22 +240,47 @@ public: void recursiveAppenderRef() { // Load a bad XML file, make sure that we don't crash in endless recursion - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMConfiguratorRecursive.xml")); - } + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMConfiguratorRecursive.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::NotConfigured); + } void invalidAppender() { // Load an XML file that attempts to use a levelmatchfilter as an appender. // We should not crash when loading this file. - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMInvalidAppender.xml")); - } + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMInvalidAppender.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::NotConfigured); + } void invalidLevel() { // Load an XML file that attempts to use a filter as a level. // We should not crash when loading this file. - DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMInvalidLevel.xml")); + auto status = DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMInvalidLevel.xml")); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); } + + void testAutoFallback() + { + std::vector<LogString> paths + { LOG4CXX_STR("input/xml") + }; + std::vector<LogString> names + { LOG4CXX_STR("DOMTestCase5_bad0.xml") + , LOG4CXX_STR("DOMTestCase5_bad1.xml") + , LOG4CXX_STR("DOMTestCase5_bad2.xml") + , LOG4CXX_STR("DOMTestCase5_bad3.xml") + , LOG4CXX_STR("DOMTestCase5_good.xml") + }; + LogString configFile; + spi::ConfigurationStatus status; + std::tie(status, configFile) = DefaultConfigurator::configureFromFile(paths, names); + LOGUNIT_ASSERT_EQUAL(status, spi::ConfigurationStatus::Configured); + LOGUNIT_ASSERT(configFile.npos != configFile.find(LOG4CXX_STR("DOMTestCase5_good.xml"))); + // Prevent "DOMTestCase5_good.xml" use in subsequent default configuration + DefaultConfigurator::setConfigurationFileName(LogString()); + } + }; LOGUNIT_TEST_SUITE_REGISTRATION(DOMTestCase); diff --git a/src/test/resources/input/xml/DOMTestCase5_bad0.xml b/src/test/resources/input/xml/DOMTestCase5_bad0.xml new file mode 100644 index 00000000..afd73782 --- /dev/null +++ b/src/test/resources/input/xml/DOMTestCase5_bad0.xml @@ -0,0 +1,22 @@ +<?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/"> +</log4j:configuration> diff --git a/src/test/resources/input/xml/DOMTestCase5_bad1.xml b/src/test/resources/input/xml/DOMTestCase5_bad1.xml new file mode 100644 index 00000000..213a8824 --- /dev/null +++ b/src/test/resources/input/xml/DOMTestCase5_bad1.xml @@ -0,0 +1,33 @@ +<?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="A1" class="org.apache.log4j.UnknownAppender"> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/> + </layout> + </appender> + + <root> + <priority value ="debug" /> + <appender-ref ref="A1" /> + </root> + +</log4j:configuration> diff --git a/src/test/resources/input/xml/DOMTestCase5_bad2.xml b/src/test/resources/input/xml/DOMTestCase5_bad2.xml new file mode 100644 index 00000000..bc26d9fc --- /dev/null +++ b/src/test/resources/input/xml/DOMTestCase5_bad2.xml @@ -0,0 +1,33 @@ +<?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 class="org.apache.log4j.FileAppender"> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%-5p %c{2} - %m%n"/> + </layout> + </appender> + + <root> + <priority value ="debug" /> + <appender-ref ref="A1" /> + </root> + +</log4j:configuration> diff --git a/src/test/resources/input/xml/DOMTestCase5_bad3.xml b/src/test/resources/input/xml/DOMTestCase5_bad3.xml new file mode 100644 index 00000000..fe1696ab --- /dev/null +++ b/src/test/resources/input/xml/DOMTestCase5_bad3.xml @@ -0,0 +1,22 @@ +<?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/"> +</log4j:confguration> diff --git a/src/test/resources/input/xml/DOMTestCase5_good.xml b/src/test/resources/input/xml/DOMTestCase5_good.xml new file mode 100644 index 00000000..568df13e --- /dev/null +++ b/src/test/resources/input/xml/DOMTestCase5_good.xml @@ -0,0 +1,33 @@ +<?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="A1" class="org.apache.log4j.ConsoleAppender"> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%Y%-5p %c{2} - %m%y%n"/> + </layout> + </appender> + + <root> + <priority value ="debug" /> + <appender-ref ref="A1" /> + </root> + +</log4j:configuration>