123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- /******************************************************************************
- *
- * package: Logging
- * file: propertyconfigurator.cpp
- * created: September 2007
- * author: Martin Heinrich
- *
- *
- * changes Feb 2009, Martin Heinrich
- * - Fixed VS 2008 unreferenced formal parameter warning by using
- * Q_UNUSED in operator<<.
- *
- *
- * Copyright 2007 - 2009 Martin Heinrich
- *
- * Licensed 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.
- *
- ******************************************************************************/
- /******************************************************************************
- * Dependencies
- ******************************************************************************/
- #include "log4qt/propertyconfigurator.h"
- #include <QtCore/QDebug>
- #include <QtCore/QFile>
- #include "log4qt/helpers/configuratorhelper.h"
- #include "log4qt/helpers/factory.h"
- #include "log4qt/helpers/optionconverter.h"
- #include "log4qt/helpers/properties.h"
- #include "log4qt/appender.h"
- #include "log4qt/layout.h"
- #include "log4qt/logger.h"
- #include "log4qt/logmanager.h"
- #include "log4qt/loggerrepository.h"
- #include "log4qt/varia/listappender.h"
- namespace Log4Qt
- {
-
-
- /**************************************************************************
- * Declarations
- **************************************************************************/
-
-
-
- /**************************************************************************
- * C helper functions
- **************************************************************************/
-
-
- LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator)
-
-
-
- /**************************************************************************
- * Class implementation: PropertyConfigurator
- **************************************************************************/
-
- bool PropertyConfigurator::doConfigure(const Properties &rProperties,
- LoggerRepository *pLoggerRepository)
- {
- startCaptureErrors();
- configureFromProperties(rProperties, pLoggerRepository);
- return stopCaptureErrors();
- }
-
-
- bool PropertyConfigurator::doConfigure(const QString &rConfigFileName,
- LoggerRepository *pLoggerRepository)
- {
- startCaptureErrors();
- configureFromFile(rConfigFileName, pLoggerRepository);
- return stopCaptureErrors();
- }
-
-
- bool PropertyConfigurator::doConfigure(const QSettings &rSettings,
- LoggerRepository *pLoggerRepository)
- {
- startCaptureErrors();
- configureFromSettings(rSettings, pLoggerRepository);
- return stopCaptureErrors();
- }
-
- bool PropertyConfigurator::configure(const Properties &rProperties)
- {
- PropertyConfigurator configurator;
- return configurator.doConfigure(rProperties);
- }
-
-
- bool PropertyConfigurator::configure(const QString &rConfigFilename)
- {
- PropertyConfigurator configurator;
- return configurator.doConfigure(rConfigFilename);
- }
-
-
- bool PropertyConfigurator::configure(const QSettings &rSettings)
- {
- PropertyConfigurator configurator;
- return configurator.doConfigure(rSettings);
- }
-
-
- bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName)
- {
- // Stop an existing watch to avoid a possible concurrent configuration
- ConfiguratorHelper::setConfigurationFile();
- if (rConfigFileName.isEmpty())
- return true;
- PropertyConfigurator configurator;
- bool result = configurator.doConfigure(rConfigFileName);
- ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure);
- return result;
- }
-
-
- void PropertyConfigurator::configureFromFile(const QString &rConfigFileName,
- LoggerRepository *pLoggerRepository)
- {
- QFile file(rConfigFileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
- {
- LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to open property file '%1'"),
- CONFIGURATOR_OPENING_FILE_ERROR,
- "Log4Qt::PropertyConfigurator");
- e << rConfigFileName;
- e.addCausingError(LogError(file.errorString(), file.error()));
- logger()->error(e);
- return;
- }
- Properties properties;
- properties.load(&file);
- if (file.error())
- {
- LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to read property file '%1'"),
- CONFIGURATOR_READING_FILE_ERROR,
- "Log4Qt::PropertyConfigurator");
- e << rConfigFileName;
- e.addCausingError(LogError(file.errorString(), file.error()));
- logger()->error(e);
- return;
- }
- configureFromProperties(properties, pLoggerRepository);
- }
-
-
- void PropertyConfigurator::configureFromProperties(const Properties &rProperties,
- LoggerRepository *pLoggerRepository)
- {
- if (!pLoggerRepository)
- pLoggerRepository = LogManager::loggerRepository();
-
- configureGlobalSettings(rProperties, pLoggerRepository);
- configureRootLogger(rProperties, pLoggerRepository);
- configureNonRootElements(rProperties, pLoggerRepository);
- mAppenderRegistry.clear();
- }
-
-
- void PropertyConfigurator::configureFromSettings(const QSettings &rSettings,
- LoggerRepository *pLoggerRepository)
- {
- Properties properties;
- properties.load(rSettings);
- configureFromProperties(properties, pLoggerRepository);
- }
-
- void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties,
- LoggerRepository *pLoggerRepository) const
- {
- Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureGlobalSettings()", "pLoggerRepository must not be null.");
- const QLatin1String key_reset("log4j.reset");
- const QLatin1String key_debug("log4j.Debug");
- const QLatin1String key_config_debug("log4j.configDebug");
- const QLatin1String key_threshold("log4j.threshold");
- const QLatin1String key_handle_qt_messages("log4j.handleQtMessages");
- // Test each global setting and set it
- // - Reset: log4j.reset
- // - Debug: log4j.Debug, log4j.configDebug
- // - Threshold: log4j.threshold
- // - Handle Qt Messages: log4j.handleQtMessages
-
- // Reset
- QString value = rProperties.property(key_reset);
- if (!value.isEmpty() && OptionConverter::toBoolean(value, false))
- {
- // Use LogManager and not pLoggerRepository to reset internal
- // logging.
- LogManager::resetConfiguration();
- logger()->debug("Reset configuration");
- }
-
- // Debug
- value = rProperties.property(key_debug);
- if (value.isNull())
- {
- value = rProperties.property(key_config_debug);
- if (!value.isNull())
- logger()->warn("[%1] is deprecated. Use [%2] instead.", key_config_debug, key_debug);
- }
- if (!value.isNull())
- {
- // Don't use OptionConverter::toLevel(). Invalid level string is a valid setting
- bool ok;
- Level level = Level::fromString(value, &ok);
- if (!ok)
- level = Level::DEBUG_INT;
- LogManager::logLogger()->setLevel(level);
- logger()->debug("Set level for Log4Qt logging to %1",
- LogManager::logLogger()->level().toString());
- }
-
- // Threshold
- value = rProperties.property(key_threshold);
- if (!value.isNull())
- {
- pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT));
- logger()->debug("Set threshold for LoggerRepository to %1",
- pLoggerRepository->threshold().toString());
- }
- // Handle Qt messages
- value = rProperties.property(key_handle_qt_messages);
- if (!value.isNull())
- {
- LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false));
- logger()->debug("Set handling of Qt messages LoggerRepository to %1",
- QVariant(LogManager::handleQtMessages()).toString());
- }
- }
-
- void PropertyConfigurator::configureNonRootElements(const Properties &rProperties,
- LoggerRepository *pLoggerRepository)
- {
- Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null.");
-
- const QString logger_prefix = QLatin1String("log4j.logger.");
- const QString category_prefix = QLatin1String("log4j.category.");
- // Iterate through all entries:
- // - Test for the logger/category prefix
- // - Convert JAVA class names to C++ ones
- // - Parse logger data (Level, Appender)
- // - Parse logger additivity
-
- QStringList keys = rProperties.propertyNames();
- QString key;
- Q_FOREACH(key, keys)
- {
- QString java_name;
- if (key.startsWith(logger_prefix))
- java_name = key.mid(logger_prefix.length());
- else if (key.startsWith(category_prefix))
- java_name = key.mid(category_prefix.length());
- QString cpp_name = OptionConverter::classNameJavaToCpp(java_name);
- if (!java_name.isEmpty())
- {
- Logger *p_logger = pLoggerRepository->logger(cpp_name);
- QString value = OptionConverter::findAndSubst(rProperties, key);
- parseLogger(rProperties, p_logger, key, value);
- parseAdditivityForLogger(rProperties, p_logger, java_name);
- }
- }
- }
-
- void PropertyConfigurator::configureRootLogger(const Properties &rProperties,
- LoggerRepository *pLoggerRepository)
- {
- Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null.");
-
- const QLatin1String key_root_logger("log4j.rootLogger");
- const QLatin1String key_root_category("log4j.rootCategory");
-
- // - Test for the logger/category prefix
- // - Parse logger data for root logger
-
- QString key = key_root_logger;
- QString value = OptionConverter::findAndSubst(rProperties, key);
- if (value.isNull())
- {
- key = key_root_category;
- value = OptionConverter::findAndSubst(rProperties, key);
- if (!value.isNull())
- logger()->warn("[%1] is deprecated. Use [%2] instead.", key_root_category, key_root_logger);
- }
- if (value.isNull())
- logger()->debug("Could not find root logger information. Is this correct?");
- else
- parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value);
- }
-
- void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties,
- Logger *pLogger,
- const QString &rLog4jName) const
- {
- Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null.");
- const QLatin1String additivity_prefix("log4j.additivity.");
-
- // - Lookup additivity key for logger
- // - Set additivity, if specified
-
- QString key = additivity_prefix + rLog4jName;
- QString value = OptionConverter::findAndSubst(rProperties, key);
- logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value);
- if (!value.isEmpty())
- {
- bool additivity = OptionConverter::toBoolean(value, true);
- logger()->debug("Setting additivity for logger '%1' to '%2'", pLogger->name(), QVariant(value).toString());
- pLogger->setAdditivity(additivity);
- }
- }
-
- LogObjectPtr<Appender> PropertyConfigurator::parseAppender(const Properties &rProperties,
- const QString &rName)
- {
- // - Test if appender has been parsed before
- // - Find appender key
- // - Create appender object
- // - Set layout, if required by appender
- // - Set properties
- // - Activate options
- // - Add appender to registry
-
- const QLatin1String appender_prefix("log4j.appender.");
-
- logger()->debug("Parsing appender named '%1'", rName);
- if (mAppenderRegistry.contains(rName))
- {
- logger()->debug("Appender '%1' was already parsed.", rName);
- return mAppenderRegistry.value(rName);
- }
- QString key = appender_prefix + rName;
- QString value = OptionConverter::findAndSubst(rProperties, key);
- if (value.isNull())
- {
- LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing appender definition for appender named '%1'"),
- CONFIGURATOR_MISSING_APPENDER_ERROR,
- "Log4Qt::PropertyConfigurator");
- e << rName;
- logger()->error(e);
- return 0;
- }
- LogObjectPtr<Appender> p_appender = Factory::createAppender(value);
- if (!p_appender)
- {
- LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' namd '%2'"),
- CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR,
- "Log4Qt::PropertyConfigurator");
- e << value << rName;
- logger()->error(e);
- return 0;
- }
- p_appender->setName(rName);
-
- if (p_appender->requiresLayout())
- {
- LogObjectPtr<Layout> p_layout = parseLayout(rProperties, key);
- if (p_layout)
- p_appender->setLayout(p_layout);
- else
- return 0;
- }
-
- QStringList exclusions;
- exclusions << QLatin1String("layout");
- setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender);
- AppenderSkeleton *p_appenderskeleton = qobject_cast<AppenderSkeleton *>(p_appender);
- if (p_appenderskeleton)
- p_appenderskeleton->activateOptions();
-
- mAppenderRegistry.insert(rName, p_appender);
- return p_appender;
- }
-
-
- LogObjectPtr<Layout> PropertyConfigurator::parseLayout(const Properties &rProperties,
- const QString &rAppenderKey)
- {
- Q_ASSERT_X(!rAppenderKey.isEmpty(), "PropertyConfigurator::parseLayout()", "rAppenderKey must not be empty.");
- // - Find layout key
- // - Create layput object
- // - Set properties
- // - Activate options
- const QLatin1String layout_suffix(".layout");
-
- logger()->debug("Parsing layout for appender named '%1'", rAppenderKey);
- QString key = rAppenderKey + layout_suffix;
- QString value = OptionConverter::findAndSubst(rProperties, key);
- if (value.isNull())
- {
- LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing layout definition for appender '%1'"),
- CONFIGURATOR_MISSING_LAYOUT_ERROR,
- "Log4Qt::PropertyConfigurator");
- e << rAppenderKey;
- logger()->error(e);
- return 0;
- }
- LogObjectPtr<Layout> p_layout = Factory::createLayout(value);
- if (!p_layout)
- {
- LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layoput of class '%1' requested by appender '%2'"),
- CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR,
- "Log4Qt::PropertyConfigurator");
- e << value << rAppenderKey;
- logger()->error(e);
- return 0;
- }
-
- QStringList exclusions;
- setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout);
- p_layout->activateOptions();
-
- return p_layout;
- }
-
-
- void PropertyConfigurator::parseLogger(const Properties &rProperties,
- Logger *pLogger,
- const QString &rKey,
- const QString &rValue)
- {
- Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null.");
- Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty.");
-
- const QLatin1String keyword_inherited("INHERITED");
-
- // - Split value on comma
- // - If level value, is specified
- // - Test for NULL and INHERITED
- // - Ensure root logger is not set to NULL
- // - Set level
- // - For each entry
- // - Create Appender
-
- logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue);
- QStringList appenders = rValue.split(QLatin1Char(','));
- QStringListIterator i (appenders);
-
- // First entry is the level. There will be always one entry, even if the rValue is
- // empty or does not contain a comma.
- QString value = i.next().trimmed();
- if (!value.isEmpty())
- {
- Level level;
- if (value.compare(keyword_inherited,Qt::CaseInsensitive) == 0)
- level = Level::NULL_INT;
- else
- level = OptionConverter::toLevel(value, Level::DEBUG_INT);
- if (level == Level::NULL_INT && pLogger->name() == QString())
- logger()->warn("The root logger level cannot be set to NULL.");
- else
- {
- pLogger->setLevel(level);
- logger()->debug("Set level for logger '%1' to '%2'",
- pLogger->name(), pLogger->level().toString());
- }
- }
-
- pLogger->removeAllAppenders();
- while(i.hasNext())
- {
- value = i.next().trimmed();
- if(value.isEmpty())
- continue;
- LogObjectPtr<Appender> p_appender = parseAppender(rProperties, value);
- if (p_appender)
- pLogger->addAppender(p_appender);
- }
- }
-
-
- void PropertyConfigurator::setProperties(const Properties &rProperties,
- const QString &rPrefix,
- const QStringList &rExclusions,
- QObject *pObject)
- {
- Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty.");
- Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null.");
-
- // Iterate through all entries:
- // - Test for prefix to determine, if setting is for object
- // - Skip empty property name
- // - Skip property names in exclusion list
- // - Set property on object
-
- logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'",
- QLatin1String(pObject->metaObject()->className()),
- rPrefix);
-
- QStringList keys = rProperties.propertyNames();
- QString key;
- Q_FOREACH(key, keys)
- {
- if (!key.startsWith(rPrefix))
- continue;
- QString property = key.mid(rPrefix.length());
- if (property.isEmpty())
- continue;
- QStringList split_property = property.split(QLatin1Char('.'));
- if (rExclusions.contains(split_property.at(0), Qt::CaseInsensitive))
- continue;
- QString value = OptionConverter::findAndSubst(rProperties, key);
- Factory::setObjectProperty(pObject, property, value);
- }
- }
-
-
- void PropertyConfigurator::startCaptureErrors()
- {
- Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty.");
-
- mpConfigureErrors = new ListAppender;
- mpConfigureErrors->setName(QLatin1String("PropertyConfigurator"));
- mpConfigureErrors->setConfiguratorList(true);
- mpConfigureErrors->setThreshold(Level::ERROR_INT);
- LogManager::logLogger()->addAppender(mpConfigureErrors);
- }
-
-
- bool PropertyConfigurator::stopCaptureErrors()
- {
- Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty.");
-
- LogManager::logLogger()->removeAppender(mpConfigureErrors);
- ConfiguratorHelper::setConfigureError(mpConfigureErrors->list());
- bool result = (mpConfigureErrors->list().count() == 0);
- mpConfigureErrors = 0;
- return result;
- }
-
-
-
- /**************************************************************************
- * Implementation: Operators, Helper
- **************************************************************************/
-
-
- #ifndef QT_NO_DEBUG_STREAM
- QDebug operator<<(QDebug debug,
- const PropertyConfigurator &rPropertyConfigurator)
- {
- Q_UNUSED(rPropertyConfigurator);
- debug.nospace() << "PropertyConfigurator("
- << ")";
- return debug.space();
- }
- #endif
-
-
-
- } // namespace Logging
|