summaryrefslogtreecommitdiff
path: root/ext/Log4Qt/src/helpers
diff options
context:
space:
mode:
authorTomasz Sterna <tomek@xiaoka.com>2014-07-11 21:06:39 +0200
committerTomasz Sterna <tomek@xiaoka.com>2014-07-11 21:06:39 +0200
commitefb33d6494d88c27c8766553b6a963ddf2654458 (patch)
tree76dd5e56b79191074998c0fb6bf7b81276116a4b /ext/Log4Qt/src/helpers
parent072da88eee57e5d16f0b75c7b90c8a0bc6a60cb3 (diff)
Included Log4Qt in project
Diffstat (limited to 'ext/Log4Qt/src/helpers')
-rw-r--r--ext/Log4Qt/src/helpers/appenderattachable.cpp199
-rw-r--r--ext/Log4Qt/src/helpers/appenderattachable.h121
-rwxr-xr-xext/Log4Qt/src/helpers/classlogger.cpp100
-rwxr-xr-xext/Log4Qt/src/helpers/classlogger.h117
-rwxr-xr-xext/Log4Qt/src/helpers/configuratorhelper.cpp136
-rwxr-xr-xext/Log4Qt/src/helpers/configuratorhelper.h211
-rwxr-xr-xext/Log4Qt/src/helpers/datetime.cpp326
-rwxr-xr-xext/Log4Qt/src/helpers/datetime.h212
-rw-r--r--ext/Log4Qt/src/helpers/dispatcher.cpp59
-rw-r--r--ext/Log4Qt/src/helpers/dispatcher.h80
-rw-r--r--ext/Log4Qt/src/helpers/factory.cpp515
-rwxr-xr-xext/Log4Qt/src/helpers/factory.h444
-rwxr-xr-xext/Log4Qt/src/helpers/initialisationhelper.cpp182
-rwxr-xr-xext/Log4Qt/src/helpers/initialisationhelper.h435
-rwxr-xr-xext/Log4Qt/src/helpers/logerror.cpp352
-rwxr-xr-xext/Log4Qt/src/helpers/logerror.h550
-rwxr-xr-xext/Log4Qt/src/helpers/logobject.cpp74
-rwxr-xr-xext/Log4Qt/src/helpers/logobject.h219
-rwxr-xr-xext/Log4Qt/src/helpers/logobjectptr.cpp65
-rwxr-xr-xext/Log4Qt/src/helpers/logobjectptr.h187
-rwxr-xr-xext/Log4Qt/src/helpers/optionconverter.cpp301
-rwxr-xr-xext/Log4Qt/src/helpers/optionconverter.h141
-rw-r--r--ext/Log4Qt/src/helpers/patternformatter.cpp902
-rwxr-xr-xext/Log4Qt/src/helpers/patternformatter.h195
-rwxr-xr-xext/Log4Qt/src/helpers/properties.cpp364
-rwxr-xr-xext/Log4Qt/src/helpers/properties.h161
26 files changed, 6648 insertions, 0 deletions
diff --git a/ext/Log4Qt/src/helpers/appenderattachable.cpp b/ext/Log4Qt/src/helpers/appenderattachable.cpp
new file mode 100644
index 0000000..2fe0c1f
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/appenderattachable.cpp
@@ -0,0 +1,199 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: appenderattachable.cpp
+ * created: Dezember 2010
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2007 Andreas Bacher
+ *
+ * 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 "helpers/appenderattachable.h"
+#include "varia/listappender.h"
+#include "appender.h"
+
+#include <QtCore/QDebug>
+
+namespace Log4Qt
+{
+
+
+/**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+/**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+/**************************************************************************
+ * Class implementation: Filter
+ **************************************************************************/
+AppenderAttachable::AppenderAttachable() :
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ mAppenderGuard()
+#else
+ mAppenderGuard(QReadWriteLock::Recursive)
+#endif
+{
+}
+
+QList<Appender *> AppenderAttachable::appenders() const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ QList<Appender *> result;
+ Appender *p_appender;
+ Q_FOREACH(p_appender, mAppenders)
+ result << p_appender;
+
+ return result;
+}
+
+void AppenderAttachable::addAppender(Appender *pAppender)
+{
+ // Avoid deadlock:
+ // - Handle warnings, before write lock is aquired
+
+ // Keep objects with a 0 reference count safe
+ LogObjectPtr < Appender > p_appender = pAppender;
+
+ {
+ QReadLocker locker(&mAppenderGuard);
+
+ if (!p_appender) {
+ //logger()->warn("Adding null Appender to Logger '%1'", name());
+ return;
+ }
+
+ if (mAppenders.contains(p_appender)) {
+ //logger()->warn("Adding of duplicate appender '%2' to logger '%1'",
+ //name(), p_appender->name());
+ return;
+ }
+ }
+ {
+ QWriteLocker locker(&mAppenderGuard);
+
+ if (mAppenders.contains(p_appender))
+ return;
+ mAppenders.append(p_appender);
+ }
+}
+
+Appender *AppenderAttachable::appender(const QString &rName) const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ Appender *p_appender;
+ Q_FOREACH(p_appender, mAppenders)
+ if (p_appender->name() == rName)
+ return p_appender;
+ return 0;
+}
+
+bool AppenderAttachable::isAttached(Appender *pAppender) const
+{
+ QReadLocker locker(&mAppenderGuard);
+
+ // Keep objects with a 0 reference count safe
+ LogObjectPtr < Appender > p_appender = pAppender;
+
+ return mAppenders.contains(p_appender);
+}
+
+void AppenderAttachable::removeAllAppenders()
+{
+// Avoid deadlock:
+// - Only log warnings without having the write log aquired
+// - Hold a reference to all appenders so that the remove does not
+// destruct the appender over the reference count while the write
+// log is held. The appender may log messages.
+
+ //logger()->trace("Removing all appenders from logger '%1'", name());
+
+ QList < LogObjectPtr<Appender> > appenders;
+ {
+ QWriteLocker locker(&mAppenderGuard);
+ QMutableListIterator < LogObjectPtr<Appender> > i(mAppenders);
+ while (i.hasNext()) {
+ Appender *p_appender = i.next();
+ ListAppender *p_listappender = qobject_cast<ListAppender*> (p_appender);
+ if (p_listappender && p_listappender->configuratorList())
+ continue;
+ else {
+ appenders << p_appender;
+ i.remove();
+ }
+ }
+ }
+ appenders.clear();
+}
+
+ void AppenderAttachable::removeAppender(Appender *pAppender)
+ {
+ // Avoid deadlock:
+ // - Only log warnings without having the write log aquired
+ // - Hold a reference to the appender so that the remove does not
+ // destruct the appender over the reference count while the write
+ // log is held. The appender may log messages.
+
+ LogObjectPtr < Appender > p_appender = pAppender;
+
+ if (!p_appender) {
+ //logger()->warn("Request to remove null Appender from Logger '%1'", name());
+ return;
+ }
+ int n;
+ {
+ QWriteLocker locker(&mAppenderGuard);
+
+ n = mAppenders.removeAll(p_appender);
+ }
+ if (n == 0) {
+ //logger()->warn(
+ // "Request to remove Appender '%2', which is not part of Logger '%1' appenders",
+ // name(), p_appender->name());
+ return;
+ }
+}
+
+void AppenderAttachable::removeAppender(const QString &rName)
+{
+ Appender *p_appender = appender(rName);
+ if (p_appender)
+ removeAppender(p_appender);
+}
+
+
+/**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/appenderattachable.h b/ext/Log4Qt/src/helpers/appenderattachable.h
new file mode 100644
index 0000000..8d1832e
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/appenderattachable.h
@@ -0,0 +1,121 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: appenderattachable.h
+ * created: December 2010
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2010 Andreas Bacher
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_APPENDERATTACHABLE_H
+#define LOG4QT_APPENDERATTACHABLE_H
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+#include "../log4qt.h"
+#include "logobjectptr.h"
+
+#include <QtCore/QList>
+#include <QtCore/QReadWriteLock>
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+class Appender;
+
+/*!
+ * \brief Implementation for attaching appenders to objects
+ */
+class LOG4QT_EXPORT AppenderAttachable
+{
+
+public:
+ AppenderAttachable();
+ virtual ~AppenderAttachable() {}
+
+ /*!
+ * Add an appender.
+ */
+ virtual void addAppender(Appender *pAppender);
+
+ /*!
+ * Get all previously added appenders as an Enumeration.
+ */
+ virtual QList<Appender *> appenders() const;
+
+ /*!
+ * Get an appender by name.
+ */
+ virtual Appender *appender(const QString &rName) const;
+
+ /*!
+ Returns <code>true</code> if the specified appender is in the
+ list of attached appenders, <code>false</code> otherwise.
+ */
+ virtual bool isAttached(Appender *pAppender) const;
+
+ /*!
+ * Removes all appenders that have been previously added from this
+ * Logger.
+ *
+ * To allow configurators to collect events during the configuration
+ * process ListAppenders with the configuratorList property set, will
+ * not be removed.
+ *
+ * \sa LisAppender::setConfiguratorList()
+ */
+ virtual void removeAllAppenders();
+
+ /*!
+ * Remove the appender passed as parameter from the list of appenders.
+ */
+ virtual void removeAppender(Appender *pAppender);
+
+ /*!
+ * Remove the appender with the name passed as parameter from the
+ * list of appenders.
+ */
+ virtual void removeAppender(const QString &rName);
+
+protected:
+ QList< LogObjectPtr<Appender> > mAppenders;
+ mutable QReadWriteLock mAppenderGuard;
+};
+
+/**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Inline
+ **************************************************************************/
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::AppenderAttachable, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_APPENDERATTACHABLE_H
diff --git a/ext/Log4Qt/src/helpers/classlogger.cpp b/ext/Log4Qt/src/helpers/classlogger.cpp
new file mode 100755
index 0000000..950fed2
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/classlogger.cpp
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: classlogger.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 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 "helpers/classlogger.h"
+
+#include <QtCore/QDebug>
+#include "logmanager.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: ClassLogger
+ **************************************************************************/
+
+
+ ClassLogger::ClassLogger() :
+ mpLogger(0)
+ {
+ }
+
+
+ Logger *ClassLogger::logger(const QObject *pObject)
+ {
+ Q_ASSERT_X(pObject, "ClassLogger::logger()", "pObject must not be null");
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ if (!mpLogger)
+ q_atomic_test_and_set_ptr(&mpLogger,
+ 0,
+ LogManager::logger(QLatin1String(pObject->metaObject()->className())));
+ return const_cast<Logger *>(mpLogger);
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ if (!static_cast<Logger *>(mpLogger))
+ mpLogger.testAndSetOrdered(0,
+ LogManager::logger(QLatin1String(pObject->metaObject()->className())));
+ return const_cast<Logger *>(static_cast<Logger *>(mpLogger));
+#else
+ if (!static_cast<Logger *>(mpLogger.loadAcquire()))
+ mpLogger.testAndSetOrdered(0,
+ LogManager::logger(QLatin1String(pObject->metaObject()->className())));
+ return const_cast<Logger *>(static_cast<Logger *>(mpLogger.loadAcquire()));
+#endif
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/classlogger.h b/ext/Log4Qt/src/helpers/classlogger.h
new file mode 100755
index 0000000..cc7bca6
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/classlogger.h
@@ -0,0 +1,117 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: classlogger.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_CLASSLOGGER_H
+#define LOG4QT_CLASSLOGGER_H
+
+#include "../log4qtshared.h"
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# include <QtCore/QAtomicPointer>
+# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+# warning "QAtomicPointer test and set is not native. The class Log4Qt::ClassLogger is not thread-safe."
+# endif
+#endif
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+ class Logger;
+
+ /*!
+ * \brief The class ClassLogger provides logging for a QObject derived
+ * class.
+ *
+ * The class ClassLogger provides a logger for a specified QObject derived
+ * object. It is used by \ref LOG4QT_DECLARE_QCLASS_LOGGER to implement the
+ * member functions provided by the macro.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa LOG4QT_DECLARE_QCLASS_LOGGER
+ */
+ class LOG4QT_EXPORT ClassLogger
+ {
+ public:
+ /*!
+ * Creates a ClassLogger object.
+ */
+ ClassLogger();
+ // ~ClassLogger(); // Use compiler default
+ // ClassLogger(const ClassLogger &rOther); // Use compiler default
+ // ClassLogger &operator=(const ClassLogger &rOther); // Use compiler default
+
+ /*!
+ * Returns a pointer to a Logger named after the class of the object
+ * \a pObject.
+ *
+ * On the first invocation the Logger is requested by a call to
+ * LogManager::logger(const char *pName). The pointer is stored to be
+ * returned on subsequent invocations.
+ *
+ * \sa LogManager::logger(const char *pName)
+ */
+ Logger *logger(const QObject *pObject);
+
+ private:
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ volatile Logger *mpLogger;
+#else
+ mutable QAtomicPointer<Logger> mpLogger;
+#endif
+ };
+
+
+ /******************************************************************************
+ * Operators, Helper
+ ******************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEinfo(Log4Qt::ClassLogger, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_CLASSLOGGER_H
diff --git a/ext/Log4Qt/src/helpers/configuratorhelper.cpp b/ext/Log4Qt/src/helpers/configuratorhelper.cpp
new file mode 100755
index 0000000..29167b2
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/configuratorhelper.cpp
@@ -0,0 +1,136 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: configuratorhelper.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/configuratorhelper.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QFileSystemWatcher>
+#include "helpers/initialisationhelper.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: ConfiguratorHelper
+ **************************************************************************/
+
+
+ ConfiguratorHelper::ConfiguratorHelper() :
+ mObjectGuard(),
+ mConfigurationFile(),
+ mpConfigureFunc(0),
+ mpConfigurationFileWatch(0),
+ mConfigureError()
+ {
+ }
+
+
+ ConfiguratorHelper::~ConfiguratorHelper()
+ {
+ delete mpConfigurationFileWatch;
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(ConfiguratorHelper)
+
+
+ void ConfiguratorHelper::doConfigurationFileChanged(const QString &rFileName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mpConfigureFunc)
+ return;
+ mpConfigureFunc(rFileName);
+ // Shall we hold the lock while emitting the signal?
+ emit configurationFileChanged(rFileName, mConfigureError.count() > 0);
+ }
+
+
+
+ void ConfiguratorHelper::doSetConfigurationFile(const QString &rFileName,
+ ConfigureFunc pConfigureFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ mConfigurationFile.clear();
+ mpConfigureFunc = 0;
+ delete mpConfigurationFileWatch;
+ if (rFileName.isEmpty())
+ return;
+
+ mConfigurationFile = rFileName;
+ mpConfigureFunc = pConfigureFunc;
+ mpConfigurationFileWatch = new QFileSystemWatcher();
+ mpConfigurationFileWatch->addPath(rFileName);
+ connect(mpConfigurationFileWatch,
+ SIGNAL(fileChanged(const QString &)),
+ SLOT(configurationFileChanged(const QString &)));
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const ConfiguratorHelper &rConfiguratorHelper)
+ {
+ debug.nospace() << "ConfiguratorHelper("
+ << "configurationfile:" << ConfiguratorHelper::configurationFile()
+ << "configurefunc:" << rConfiguratorHelper.mpConfigureFunc
+ << "filesystemwatcher:" << rConfiguratorHelper.mpConfigurationFileWatch
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/helpers/configuratorhelper.h b/ext/Log4Qt/src/helpers/configuratorhelper.h
new file mode 100755
index 0000000..45fe670
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/configuratorhelper.h
@@ -0,0 +1,211 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: configuratorhelper.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_CONFIGURATORHELPER_H
+#define LOG4QT_HELPERS_CONFIGURATORHELPER_H
+
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+
+#include <QtCore/QList>
+#include <QtCore/QMutex>
+#include "loggingevent.h"
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QFileSystemWatcher;
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class ConfiguratorHelper provides a confiuration file watch
+ * and last error for configurator classes.
+ *
+ * A configuration file can be set using setConfigurationFile(). The file
+ * is watched for changes. If a change occurs the configuration is reloaded
+ * and the ConfigurationFileChanged() signal is emitted. Error information
+ * for the last call to a configure function or the last configuration file
+ * change can be accessed using configureError().
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+ class LOG4QT_EXPORT ConfiguratorHelper : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ /*!
+ * Prototype for a configure callback function. The function is called
+ * when then configuration file is changed and takes the
+ * configuration file as a parameter.
+ *
+ * \sa setConfigurationFile(),
+ * PropertyConfigurator::configure(const QString &)
+ */
+ typedef bool (*ConfigureFunc)(const QString &rFileName);
+
+ private:
+ ConfiguratorHelper();
+ ConfiguratorHelper(const ConfiguratorHelper &rOther); // Not implemented
+ virtual ~ConfiguratorHelper();
+ ConfiguratorHelper &operator=(const ConfiguratorHelper &rOther); // Not implemented
+
+ public:
+
+ /*!
+ * Returns the error information for the last configuration operation
+ * that took place. The configuration operation could be the result of
+ * a call to one of the configure methods or through a change
+ * to the configuration file.
+ *
+ * \sa setConfigureError(), PropertyConfigurator::configure(),
+ * setConfigurationFile()
+ */
+ static QList<LoggingEvent> configureError();
+
+ /*!
+ * Returns the current configuration file.
+ *
+ * \sa setConfigurationFile()
+ */
+ static QString configurationFile();
+
+ /*!
+ * Returns the ConfiguratorHelper instance.
+ */
+ static ConfiguratorHelper *instance();
+
+ /*!
+ * Sets the configuration error information for the last configuration
+ * operation.
+ *
+ * \sa configureError()
+ */
+ static void setConfigureError(const QList<LoggingEvent> &rConfigureError);
+
+ /*!
+ * Sets the configuration file to \a rFileName. The file is watched for
+ * changes. On a file change the function \a pConfigureFunc will be called
+ * and the signal configurationFileChange() will be emitted.
+ *
+ * Setting the configuration file to an empty string stops the file watch.
+ *
+ * \sa configurationFile(), PropertyConfigurator::configureAndWatch(),
+ * configureError()
+ */
+ static void setConfigurationFile(const QString &rFileName = QString(),
+ ConfigureFunc pConfigureFunc = 0);
+
+ signals:
+ /*!
+ * The signal is emitted after a change to the file \a rFileName
+ * was processed. If an error occured during the configuration, the
+ * flag \a error will be true and error information is available
+ * over configureError().
+ */
+ void configurationFileChanged(const QString &rFileName,
+ bool error);
+
+ private slots:
+ void doConfigurationFileChanged(const QString &rFileName);
+
+ private:
+ void doSetConfigurationFile(const QString &rFileName,
+ ConfigureFunc pConfigureFunc);
+
+ private:
+ mutable QMutex mObjectGuard;
+ QString mConfigurationFile;
+ ConfigureFunc mpConfigureFunc;
+ QFileSystemWatcher *mpConfigurationFileWatch;
+ QList<LoggingEvent> mConfigureError;
+
+#ifndef QT_NO_DEBUG_STREAM
+ // Needs to be friend to access details
+ friend QDebug operator<<(QDebug debug,
+ const ConfiguratorHelper &rConfiguratorHelper);
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates ConfiguratorHelper
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %ConfiguratorHelper(configurationfile: "" configurefunc: false
+ * filesystemwatcher: QObject(0x0) )
+ * </tt>
+ * \sa QDebug, ConfiguratorHelper::logManager()
+ */
+ QDebug operator<<(QDebug debug,
+ const ConfiguratorHelper &rConfiguratorHelper);
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QList<LoggingEvent> ConfiguratorHelper::configureError()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mConfigureError; }
+
+ inline QString ConfiguratorHelper::configurationFile()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mConfigurationFile; }
+
+ inline void ConfiguratorHelper::setConfigureError(const QList<LoggingEvent> &rConfigureError)
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ instance()->mConfigureError = rConfigureError; }
+
+ inline void ConfiguratorHelper::setConfigurationFile(const QString &rFileName,
+ ConfigureFunc pConfigureFunc)
+ { instance()->doSetConfigurationFile(rFileName, pConfigureFunc); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::ConfiguratorHelper, Q_COMPLEX_TYPE); // use default
+
+
+#endif // LOG4QT_HELPERS_CONFIGURATORHELPER_H
diff --git a/ext/Log4Qt/src/helpers/datetime.cpp b/ext/Log4Qt/src/helpers/datetime.cpp
new file mode 100755
index 0000000..a51b8eb
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/datetime.cpp
@@ -0,0 +1,326 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: datetime.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/datetime.h"
+
+#include <QtCore/QDebug>
+#include "helpers/initialisationhelper.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: DateTime
+ **************************************************************************/
+
+
+ QString DateTime::toString(const QString &rFormat) const
+ {
+ QString format(rFormat);
+
+ if (format.isEmpty())
+ return QString();
+ if (!isValid())
+ return QString();
+ if (format == QLatin1String("NONE"))
+ return QString();
+
+ if (format == QLatin1String("RELATIVE"))
+ return QString::number(toMilliSeconds() - InitialisationHelper::startTime());
+
+ if (format == QLatin1String("ISO8601"))
+ format = QLatin1String("yyyy-MM-dd hh:mm:ss.zzz");
+ if (format == QLatin1String("ABSOLUTE"))
+ format = QLatin1String("HH:mm:ss.zzz");
+ if (format == QLatin1String("DATE"))
+ format = QLatin1String("dd MMM YYYY HH:mm:ss.zzzz");
+
+ return formatDateTime(format);
+ }
+
+
+ QString DateTime::formatDateTime(const QString &rFormat) const
+ {
+ if (rFormat.isEmpty())
+ return QString();
+ if (!isValid())
+ return QString();
+
+ const QLatin1Char null('0');
+ const QLatin1Char quote('\'');
+ const QString tokens = QLatin1String("\'dMyhHmszAPapw");
+ const bool am_pm = hasAMPM(rFormat);
+
+ QString result;
+ QString token;
+ QChar expected = null;
+
+ QChar c;
+ int i;
+ for (i = 0; i < rFormat.length(); i++)
+ {
+ c = rFormat.at(i);
+
+ // Handle literal text
+ if (expected == quote)
+ {
+ if (c == quote)
+ {
+ Q_ASSERT_X(i > 0, "DateTime::toString()", "Found quote with status quote at i = 0");
+ if (i > 0 && rFormat.at(i - 1) == quote)
+ // Second of two quotes
+ result += quote;
+ expected = null;
+ }
+ else
+ // Next literal character
+ result += c;
+ }
+ else if (c == expected)
+ {
+ // Extend token
+ token += c;
+ }
+ else
+ {
+ // Close last token
+ result += formatToken(token, am_pm);
+ token.clear();
+ expected = null;
+
+ // Test for valid character
+ if (tokens.indexOf(c) >= 0)
+ {
+ if (c == QLatin1Char('a'))
+ expected = QLatin1Char('p');
+ else if (c == QLatin1Char('A'))
+ expected = QLatin1Char('P');
+ else if (c.toLower() == QLatin1Char('p'))
+ expected = null;
+ else
+ expected = c;
+ if (c != quote)
+ token += c;
+ } else
+ result += c;
+ }
+ }
+
+ result += formatToken(token, am_pm);
+ return result;
+ }
+
+
+ QString DateTime::formatToken(const QString &rToken, bool am_pm) const
+ {
+ if (rToken.isEmpty())
+ return QString();
+
+ const QChar c = rToken.at(0);
+ QString result;
+ int used = 0;
+
+ // Qt data format strings
+ if (rToken.startsWith(QLatin1String("dddd")))
+ {
+ result = QDate::longDayName(date().dayOfWeek());
+ used = 4;
+ }
+ else if (rToken.startsWith(QLatin1String("ddd")))
+ {
+ result = QDate::shortDayName(date().dayOfWeek());
+ used = 3;
+ }
+ else if (rToken.startsWith(QLatin1String("dd")))
+ {
+ result = QString::number(date().day()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('d'))
+ {
+ result = QString::number(date().day());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("MMMM")))
+ {
+ result = QDate::longMonthName(date().month());
+ used = 4;
+ }
+ else if (rToken.startsWith(QLatin1String("MMM")))
+ {
+ result = QDate::shortMonthName(date().month());
+ used = 3;
+ }
+ else if (rToken.startsWith(QLatin1String("MM")))
+ {
+ result = QString::number(date().month()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('M'))
+ {
+ result = QString::number(date().month());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("yyyy")))
+ {
+ result = QString::number(date().year());
+ used = 4;
+ }
+ else if (rToken.startsWith(QLatin1String("yy")))
+ {
+ result = QString::number(date().year() % 100).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+
+ // Qt time format strings
+ else if (rToken.startsWith(QLatin1String("hh")) || rToken.startsWith(QLatin1String("HH")))
+ {
+ int hour = time().hour();
+ if (am_pm && c == QLatin1Char('h') && hour > 12)
+ hour -= 12;
+ result = QString::number(hour).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('h') || c == QLatin1Char('H'))
+ {
+ int hour = time().hour();
+ if (am_pm && c == QLatin1Char('h') && hour > 12)
+ hour -= 12;
+ result = QString::number(hour);
+ used = 2;
+ }
+ else if (rToken.startsWith(QLatin1String("mm")))
+ {
+ result = QString::number(time().minute()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == (QLatin1Char('m')))
+ {
+ result = QString::number(time().minute());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("ss")))
+ {
+ result = QString::number(time().second()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('s'))
+ {
+ result = QString::number(time().second());
+ used = 1;
+ }
+ else if (rToken.startsWith(QLatin1String("zzz")))
+ {
+ result = QString::number(time().msec()).rightJustified(3, QLatin1Char('0'), true);
+ used = 3;
+ }
+ else if (c == QLatin1Char('z'))
+ {
+ result = QString::number(time().msec());
+ used = 1;
+ }
+ else if (c.toLower() == QLatin1Char('a'))
+ {
+ bool is_lower = c == QLatin1Char('a');
+ if (time().hour() < 12)
+ result = QLatin1String("AM");
+ else
+ result = QLatin1String("PM");
+ if (is_lower)
+ result = result.toLower();
+ if (rToken.size() > 1 &&
+ ((is_lower && rToken.at(1) == QLatin1Char('p')) ||
+ (!is_lower && rToken.at(1) == QLatin1Char('P')))
+ )
+ used = 2;
+ else
+ used = 1;
+ }
+
+ // Extension for week number
+ else if (rToken.startsWith(QLatin1String("ww")))
+ {
+ result = QString::number(date().weekNumber()).rightJustified(2, QLatin1Char('0'), true);
+ used = 2;
+ }
+ else if (c == QLatin1Char('w'))
+ {
+ result = QString::number(date().weekNumber());
+ used = 1;
+ }
+
+ if (used)
+ return result + formatToken(rToken.mid(used), am_pm);
+ else
+ return result;
+ }
+
+
+ bool DateTime::hasAMPM(const QString &rToken)
+ {
+ bool in_literal = false;
+ QChar c;
+ int i;
+ for (i = 0; i < rToken.length(); i++)
+ {
+ c = rToken.at(i);
+ if (c == QLatin1Char('\''))
+ in_literal = !in_literal;
+ else if (!in_literal && c.toLower() == QLatin1Char('a'))
+ return true;
+ }
+ return false;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/datetime.h b/ext/Log4Qt/src/helpers/datetime.h
new file mode 100755
index 0000000..19a074f
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/datetime.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: datetime.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Resolved compilation problem with Microsoft Visual Studio 2005
+ *
+ *
+ * Copyright 2007 - 2008 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_DATETIME_H
+#define LOG4QT_HELPERS_DATETIME_H
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QDateTime>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ /*!
+ * \brief The class DateTime provides extended functionality for QDateTime.
+ *
+ * The class DateTime implements additional formatting options for
+ * toString() and provides conversion functions from and to milliseconds.
+ */
+ class LOG4QT_EXPORT DateTime : public QDateTime
+ {
+ public:
+ /*!
+ * Constructs a null date time.
+ *
+ * \sa QDateTime::QDateTime()
+ */
+ DateTime();
+
+ // DateTime(const DateTime &rOther); // Use compiler default
+
+ /*!
+ * Constructs a copy of another QDateTime.
+ *
+ * \sa QDateTime::QDateTime(const QDateTime &rOther)
+ */
+ DateTime(const QDateTime &rOther);
+
+ /*!
+ * Constructs a datetime with the given \a rDate and \a rTime, using
+ * the time specification defined by \a timeSpec.
+ *
+ * \sa QDateTime::QDateTime(const QDate &rDate, const QTime &rTime,
+ * Qt::TimeSpec timeSpec = Qt::LocalTime)
+ */
+ DateTime(const QDate &rDate,
+ const QTime &rTime,
+ Qt::TimeSpec timeSpec = Qt::LocalTime);
+
+ // virtual ~DateTime(); // Use compiler default
+
+ /*!
+ * Assigns \a rOther to this DateTime and returns a reference to it.
+ */
+ DateTime &operator=(const DateTime &rOther);
+
+ /*!
+ * Returns the datetime as the number of milliseconds that have passed
+ * since 1970-01-01T00:00:00,000, Coordinated Universal Time (Qt::UTC).
+ *
+ * \sa QDateTime::toTime_t()
+ */
+ qint64 toMilliSeconds() const;
+
+ /*!
+ * Returns the datetime as a string. The \a rFormat parameter
+ * determines the format of the result string.
+ *
+ * In addition to the expressions of QDateTime::toString(const QString
+ * &rFormat) the following expression can be used.
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="20%"> Expression </th>
+ * <th> Output </th>
+ * </tr><tr>
+ * <td> w </td>
+ * <td> the week of the year as number without a leading zero (1 to 53) </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> ww </td>
+ * <td> the week of the year as number with a leading zero (01 to 53) </td>
+ * </tr>
+ * </table>
+ *
+ * Alternatively the \a rFormat parameter can specify one of the
+ * following strings.
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="20%"> String </th>
+ * <th> Format </th>
+ * </tr><tr>
+ * <td> ABSOLUTE </td>
+ * <td> uses the format HH:mm:ss.zzz </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> DATE </td>
+ * <td> uses the format dd MMM YYYY HH:mm:ss.zzzz </td>
+ * </tr><tr>
+ * <td> ISO8601 </td>
+ * <td> uses the format yyyy-MM-dd hh:mm:ss.zzz </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> NONE </td>
+ * <td> uses an empty string as format </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> RELATIVE </td>
+ * <td> returns the milliseconds since start of the program</td>
+ * </tr>
+ * </table>
+ *
+ * \sa QDateTime::toString(const QString &rFormat)
+ */
+ QString toString(const QString &rFormat) const;
+
+ /*!
+ * Returns the current datetime, as reported by the system clock, in
+ * the local time zone.
+ *
+ * \sa QDateTime::currentDateTime()
+ */
+ static DateTime currentDateTime();
+
+ /*!
+ * Returns a datetime whose date and time are the number of
+ * milliseconds that have passed since 1970-01-01T00:00:00,
+ * Coordinated Universal Time (Qt::UTC).
+ *
+ * \sa QDateTime::fromTime_t(uint seconds)
+ */
+ static DateTime fromMilliSeconds(qint64 milliSeconds);
+
+ private:
+ QString formatDateTime(const QString &rFormat) const;
+ QString formatToken(const QString &rToken, bool am_pm) const;
+ static bool hasAMPM(const QString &rFormat);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline DateTime::DateTime() : QDateTime()
+ {}
+
+ inline DateTime::DateTime(const QDateTime &rOther) : QDateTime(rOther)
+ {}
+
+ inline DateTime::DateTime(const QDate &rDate,
+ const QTime &rTime,
+ Qt::TimeSpec timeSpec) :
+ QDateTime(rDate, rTime, timeSpec)
+ {}
+
+ inline DateTime &DateTime::operator=(const DateTime &rOther)
+ { QDateTime::operator=(rOther); return *this; }
+
+ inline qint64 DateTime::toMilliSeconds() const
+ { return static_cast<qint64>(1000) * toTime_t() + time().msec(); }
+
+ inline DateTime DateTime::currentDateTime()
+ { return DateTime(QDateTime::currentDateTime()); }
+
+ inline DateTime DateTime::fromMilliSeconds(qint64 milliSeconds)
+ { return DateTime(QDateTime::fromTime_t(milliSeconds / 1000).addMSecs(milliSeconds % 1000)); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::DateTime, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_HELPERS_DATETIME_H
diff --git a/ext/Log4Qt/src/helpers/dispatcher.cpp b/ext/Log4Qt/src/helpers/dispatcher.cpp
new file mode 100644
index 0000000..08d385f
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/dispatcher.cpp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: dispatcher.cpp
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#include "dispatcher.h"
+#include "loggingevent.h"
+#include "asyncappender.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+
+namespace Log4Qt
+{
+
+/**************************************************************************
+ * Class implementation: Dispatcher
+ **************************************************************************/
+Dispatcher::Dispatcher(QObject *parent) : QObject(parent)
+ , mpAsyncAppender(0)
+{}
+
+void Dispatcher::customEvent(QEvent* event)
+{
+ if (event->type() == LoggingEvent::eventId)
+ {
+ LoggingEvent *logEvent = static_cast<LoggingEvent*>(event);
+ if (mpAsyncAppender)
+ mpAsyncAppender->callAppenders(*logEvent);
+ }
+ QObject::customEvent(event);
+}
+
+void Dispatcher::setAsyncAppender(AsyncAppender *pAsyncAppender)
+{
+ mpAsyncAppender = pAsyncAppender;
+}
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/dispatcher.h b/ext/Log4Qt/src/helpers/dispatcher.h
new file mode 100644
index 0000000..00e7167
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/dispatcher.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: dispatcher.h
+ * created: February 2011
+ * author: Andreas Bacher
+ *
+ *
+ * Copyright 2011 Andreas Bacher
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QTDISPATCHER_H
+#define LOG4QTDISPATCHER_H
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QThread>
+#include <QtCore/QList>
+
+#include "loggingevent.h"
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+class AsyncAppender;
+
+/*!
+ * \brief The class Dispatcher does the actual logging to the attached appanders.
+ *
+ * The Dispatcher is the worker object which class the attached apperders in the
+ * the context of the DispatcherThread.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ */
+class Dispatcher : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Dispatcher(QObject *parent = 0);
+
+ void setAsyncAppender(AsyncAppender *pAsyncAppender);
+
+protected:
+ virtual void customEvent(QEvent* event);
+
+private:
+ AsyncAppender *mpAsyncAppender;
+};
+
+
+/**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+/**************************************************************************
+ * Inline
+ **************************************************************************/
+} // namespace Log4Qt
+
+#endif // DISPATCHER_H
diff --git a/ext/Log4Qt/src/helpers/factory.cpp b/ext/Log4Qt/src/helpers/factory.cpp
new file mode 100644
index 0000000..f5411b5
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/factory.cpp
@@ -0,0 +1,515 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: factory.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/factory.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaObject>
+#include <QtCore/QMetaProperty>
+#include "consoleappender.h"
+#include "colorconsoleappender.h"
+#include "dailyrollingfileappender.h"
+#include "fileappender.h"
+#include "helpers/logerror.h"
+#include "helpers/initialisationhelper.h"
+#include "helpers/optionconverter.h"
+#include "patternlayout.h"
+#include "rollingfileappender.h"
+#include "signalappender.h"
+#include "simplelayout.h"
+#include "simpletimelayout.h"
+#include "ttcclayout.h"
+
+#if defined(QT_NETWORK_LIB)
+#include "telnetappender.h"
+#endif
+
+#if defined(QT_SQL_LIB)
+#include "databaseappender.h"
+#include "databaselayout.h"
+#endif //#ifdef QT_SQL_LIB
+
+#include "varia/debugappender.h"
+#include "varia/denyallfilter.h"
+#include "varia/levelmatchfilter.h"
+#include "varia/levelrangefilter.h"
+#include "varia/listappender.h"
+#include "varia/nullappender.h"
+#include "varia/stringmatchfilter.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Factory)
+
+
+ // Appenders
+
+ Appender *console_file_appender()
+ { return new ConsoleAppender; }
+
+ Appender *create_daily_rolling_file_appender()
+ { return new DailyRollingFileAppender; }
+
+ Appender *create_debug_appender()
+ { return new DebugAppender; }
+
+ Appender *create_file_appender()
+ { return new FileAppender; }
+
+ Appender *create_list_appender()
+ { return new ListAppender; }
+
+ Appender *create_null_appender()
+ { return new NullAppender; }
+
+ Appender *create_rolling_file_appender()
+ { return new RollingFileAppender; }
+
+ Appender *create_signal_appender()
+ { return new SignalAppender; }
+
+ Appender *create_color_console_appender()
+ { return new ColorConsoleAppender;}
+
+#if defined(QT_SQL_LIB)
+ Appender *create_database_appender()
+ { return new DatabaseAppender; }
+#endif //#if defined(QT_SQL_LIB)
+
+#if defined(QT_NETWORK_LIB)
+ Appender *create_telnet_appender()
+ { return new TelnetAppender; }
+#endif
+ // Filters
+
+ Filter *create_deny_all_filter()
+ { return new DenyAllFilter; }
+
+ Filter *create_level_match_filter()
+ { return new LevelMatchFilter; }
+
+ Filter *create_level_range_filter()
+ { return new LevelRangeFilter; }
+
+ Filter *create_string_match_filter()
+ { return new StringMatchFilter; }
+
+
+ // Layouts
+
+ Layout *create_pattern_layout()
+ { return new PatternLayout; }
+
+ Layout *create_simple_layout()
+ { return new SimpleLayout; }
+
+ Layout *create_simple_time_layout()
+ { return new SimpleTimeLayout; }
+
+#if defined(QT_SQL_LIB)
+ Layout *create_database_layout()
+ { return new DatabaseLayout; }
+#endif //#if defined(QT_SQL_LIB)
+
+ Layout *create_ttcc_layout()
+ { return new TTCCLayout; }
+
+
+
+ /**************************************************************************
+ * Class implementation: Factory
+ **************************************************************************/
+
+
+ Factory::Factory() :
+ mObjectGuard(),
+ mAppenderRegistry(),
+ mFilterRegistry(),
+ mLayoutRegistry()
+ {
+ registerDefaultAppenders();
+ registerDefaultFilters();
+ registerDefaultLayouts();
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(Factory)
+
+
+ Appender *Factory::doCreateAppender(const QString &rAppenderClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mAppenderRegistry.contains(rAppenderClassName))
+ {
+ logger()->warn("Request for the creation of Appender with class '%1', which is not registered", rAppenderClassName);
+ return 0;
+ }
+ return mAppenderRegistry.value(rAppenderClassName)();
+ }
+
+
+ Filter *Factory::doCreateFilter(const QString &rFilterClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mFilterRegistry.contains(rFilterClassName))
+ {
+ logger()->warn("Request for the creation of Filter with class '%1', which is not registered", rFilterClassName);
+ return 0;
+ }
+ return mFilterRegistry.value(rFilterClassName)();
+ }
+
+
+ Layout *Factory::doCreateLayout(const QString &rLayoutClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mLayoutRegistry.contains(rLayoutClassName))
+ {
+ logger()->warn("Request for the creation of Layout with class '%1', which is not registered", rLayoutClassName);
+ return 0;
+ }
+ return mLayoutRegistry.value(rLayoutClassName)();
+ }
+
+
+ void Factory::doRegisterAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if(rAppenderClassName.isEmpty())
+ {
+ logger()->warn("Registering Appender factory function with empty class name");
+ return;
+ }
+ mAppenderRegistry.insert(rAppenderClassName, pAppenderFactoryFunc);
+ }
+
+
+ void Factory::doRegisterFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if(rFilterClassName.isEmpty())
+ {
+ logger()->warn("Registering Filter factory function with empty class name");
+ return;
+ }
+ mFilterRegistry.insert(rFilterClassName, pFilterFactoryFunc);
+ }
+
+
+ void Factory::doRegisterLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if(rLayoutClassName.isEmpty())
+ {
+ logger()->warn("Registering Layout factory function with empty class name");
+ return;
+ }
+ mLayoutRegistry.insert(rLayoutClassName, pLayoutFactoryFunc);
+ }
+
+
+ void Factory::doSetObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue)
+ {
+ // - Validate property
+ // - Get correct property name from meta object
+ // - Find specific property setter
+ // - If no specfifc propery setter can be found,
+ // find general property setter
+ // - Call property setter
+
+ QMetaProperty meta_property;
+ if (!validateObjectProperty(meta_property, rProperty, pObject))
+ return;
+
+ QString property = QLatin1String(meta_property.name());
+ QString type = QLatin1String(meta_property.typeName());
+ logger()->debug("Setting property '%1' on object of class '%2' to value '%3'",
+ property,
+ QLatin1String(pObject->metaObject()->className()),
+ rValue);
+
+ QVariant value;
+ bool ok = true;
+ if (type == QLatin1String("bool"))
+ value = OptionConverter::toBoolean(rValue, &ok);
+ else if (type == QLatin1String("int"))
+ value = OptionConverter::toInt(rValue, &ok);
+ else if (type == QLatin1String("Log4Qt::Level"))
+ value = QVariant::fromValue(OptionConverter::toLevel(rValue, &ok));
+ else if (type == QLatin1String("QString"))
+ value = rValue;
+ else
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Cannot convert to type '%1' for property '%2' on object of class '%3'"),
+ CONFIGURATOR_UNKNOWN_TYPE_ERROR,
+ "Log4Qt::Factory");
+ e << type
+ << property
+ << QString::fromLatin1(pObject->metaObject()->className());
+ logger()->error(e);
+ return;
+ }
+ if (!ok)
+ return;
+
+ // Everything is checked and the type is the one of the property.
+ // Write should never return false
+ if (!meta_property.write(pObject, value))
+ logger()->warn("Unxpected error result from QMetaProperty.write()");
+ }
+
+
+ void Factory::doUnregisterAppender(const QString &rAppenderClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mAppenderRegistry.contains(rAppenderClassName))
+ {
+ logger()->warn("Request to unregister not registered Appender factory function for class '%1'", rAppenderClassName);
+ return;
+ }
+ mAppenderRegistry.remove(rAppenderClassName);
+ }
+
+
+ void Factory::doUnregisterFilter(const QString &rFilterClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mFilterRegistry.contains(rFilterClassName))
+ {
+ logger()->warn("Request to unregister not registered Filter factory function for class '%1'", rFilterClassName);
+ return;
+ }
+ mFilterRegistry.remove(rFilterClassName);
+ }
+
+
+ void Factory::doUnregisterLayout(const QString &rLayoutClassName)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (!mLayoutRegistry.contains(rLayoutClassName))
+ {
+ logger()->warn("Request to unregister not registered Layout factory function for class '%1'", rLayoutClassName);
+ return;
+ }
+ mLayoutRegistry.remove(rLayoutClassName);
+ }
+
+
+ void Factory::registerDefaultAppenders()
+ {
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ConsoleAppender"), console_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::ConsoleAppender"), console_file_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DailyRollingFileAppender"), create_daily_rolling_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::DailyRollingFileAppender"), create_daily_rolling_file_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.DebugAppender"), create_debug_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::DebugAppender"), create_debug_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.FileAppender"), create_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::FileAppender"), create_file_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.ListAppender"), create_list_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::ListAppender"), create_list_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.varia.NullAppender"), create_null_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::NullAppender"), create_null_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.RollingFileAppender"), create_rolling_file_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::RollingFileAppender"), create_rolling_file_appender);
+
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.SignalAppender"), create_signal_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::SignalAppender"), create_signal_appender);
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.ColorConsoleAppender"), create_color_console_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::ColorConsoleAppender"), create_color_console_appender);
+
+#if defined(QT_SQL_LIB)
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.DatabaseAppender"), create_database_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::DatabaseAppender"), create_database_appender);
+#endif //#ifdef QT_SQL_LIB
+
+#if defined(QT_NETWORK_LIB)
+ mAppenderRegistry.insert(QLatin1String("org.apache.log4j.TelnetAppender"), create_telnet_appender);
+ mAppenderRegistry.insert(QLatin1String("Log4Qt::TelnetAppender"), create_telnet_appender);
+#endif
+ }
+
+
+ void Factory::registerDefaultFilters()
+ {
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.DenyAllFilter"), create_deny_all_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::DenyAllFilter"), create_deny_all_filter);
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelMatchFilter"), create_level_match_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::LevelMatchFilter"), create_level_match_filter);
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.LevelRangeFilter"), create_level_range_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::LevelRangeFilter"), create_level_range_filter);
+ mFilterRegistry.insert(QLatin1String("org.apache.log4j.varia.StringMatchFilter"), create_string_match_filter);
+ mFilterRegistry.insert(QLatin1String("Log4Qt::StringMatchFilter"), create_string_match_filter);
+ }
+
+
+ void Factory::registerDefaultLayouts()
+ {
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.PatternLayout"), create_pattern_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::PatternLayout"), create_pattern_layout);
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleLayout"), create_simple_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleLayout"), create_simple_layout);
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.TTCCLayout"), create_ttcc_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::TTCCLayout"), create_ttcc_layout);
+
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.SimpleTimeLayout"), create_simple_time_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::SimpleTimeLayout"), create_simple_time_layout);
+
+#if defined(QT_SQL_LIB)
+ mLayoutRegistry.insert(QLatin1String("org.apache.log4j.DatabaseLayout"), create_database_layout);
+ mLayoutRegistry.insert(QLatin1String("Log4Qt::DatabaseLayout"), create_database_layout);
+#endif //#ifdef (QT_SQL_LIB)
+ }
+
+
+ bool Factory::validateObjectProperty(QMetaProperty &rMetaProperty,
+ const QString &rProperty,
+ QObject *pObject)
+ {
+ // Validate:
+ // - No null object pointer
+ // - No empty property name
+ // - Property exists on the object (QT or Java name)
+ // - Property is readable
+ // - Property is writable
+
+ const char *p_context = "Log4Qt::Factory";
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to set property value on object"),
+ CONFIGURATOR_PROPERTY_ERROR,
+ p_context);
+
+ if (!pObject)
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid null object pointer"),
+ 0,
+ p_context);
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+ if (rProperty.isEmpty())
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Invalid empty property name"),
+ 0,
+ p_context);
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+ const QMetaObject *p_meta_object = pObject->metaObject();
+ QString property = rProperty;
+ int i = p_meta_object->indexOfProperty(property.toLatin1());
+ if (i < 0)
+ {
+ // Try name with lower case first character. Java properties names
+ // start upper case
+ property[0] = property[0].toLower();
+ i = p_meta_object->indexOfProperty(property.toLatin1());
+ if (i < 0)
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' does not exist in class '%2'"),
+ 0,
+ p_context);
+ ce << property
+ << QString::fromLatin1(pObject->metaObject()->className());
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+ }
+ rMetaProperty = p_meta_object->property(i);
+ if (!rMetaProperty.isWritable())
+ {
+ LogError ce = LOG4QT_ERROR(QT_TR_NOOP("Property '%1' is not writable in class '%2'"),
+ 0,
+ p_context);
+ ce << property
+ << QString::fromLatin1(pObject->metaObject()->className());
+ e.addCausingError(ce);
+ logger()->error(e);
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const Factory &rFactory)
+ {
+ debug.nospace() << "Factory("
+ << "appenderfactories:" << rFactory.registeredAppenders()
+ << "filterfactories:" << rFactory.registeredFilters()
+ << "layoutfactories:" << rFactory.registeredLayouts()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
+
diff --git a/ext/Log4Qt/src/helpers/factory.h b/ext/Log4Qt/src/helpers/factory.h
new file mode 100755
index 0000000..365f1ea
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/factory.h
@@ -0,0 +1,444 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: factory.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_FACTORY_H
+#define LOG4QT_HELPERS_FACTORY_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QHash>
+#include <QtCore/QMutex>
+#include <QtCore/QStringList>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+
+ class Appender;
+ class Filter;
+ class Layout;
+
+ /*!
+ * \brief The class Factory provides factories for Appender, Filter and
+ * Layout objects.
+ *
+ * The functions createAppender(), createFilter() and createLayout()
+ * allow to create objects by specifying their class names. By default
+ * all classes of the package are recognised with their Log4j and Log4Qt
+ * classanmes. For example an object of the class FileAppender can be
+ * craeted using "org.apache.log4j.FileAppender" or "Log4Qt::FileAppender".
+ * Additional classes can be registered using registerAppender(),
+ * registerFilter() and registerLayout().
+ *
+ * An QObject property can be set from a string value with
+ * setObjectProperty(). The function handles the required error checking
+ * and type conversion.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa PropertyConfigurator
+ */
+ class LOG4QT_EXPORT Factory
+ {
+ public:
+ /*!
+ * Prototype for an Appender factory function. The function creates
+ * an Appender object on the heap and returns a pointer to it.
+ *
+ * \sa registerAppender(), createAppender()
+ */
+ typedef Appender *(*AppenderFactoryFunc)();
+
+ /*!
+ * Prototype for a Filter factory function. The function creates
+ * a Filter object on the heap and returns a pointer to it.
+ *
+ * \sa registerFilter(), createFilter()
+ */
+ typedef Filter *(*FilterFactoryFunc)();
+
+ /*!
+ * Prototype for a Layout factory function. The function creates
+ * a Layout object on the heap and returns a pointer to it.
+ *
+ * \sa registerLayout(), createLayout()
+ */
+ typedef Layout *(*LayoutFactoryFunc)();
+
+ private:
+ Factory();
+ Factory(const Factory &rOther); // Not implemented
+ // virtual ~Factory(); // Use compiler default
+ Factory &operator=(const Factory &rOther); // Not implemented
+
+ public:
+ /*!
+ * Creates an object for the class \a rAppenderClassName on the heap
+ * and returns a pointer to it. If the class has no registered factory
+ * function a null pointer is returned.
+ *
+ * \sa registerAppender(), unregisterAppender(), registeredAppenders()
+ */
+ static Appender *createAppender(const QString &rAppenderClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static Appender *createAppender(const char *pAppenderClassName);
+
+ /*!
+ * Creates an object for the class \a rFilterClassName on the heap
+ * and returns a pointer to it. If the class has no registered factory
+ * function a null pointer is returned.
+ *
+ * \sa registerFilter(), unregisterFilter(), registeredFilters()
+ */
+ static Filter *createFilter(const QString &rFilterClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static Filter *createFilter(const char *pFilterClassName);
+
+ /*!
+ * Creates an object for the class \a rLayoutClassName on the heap
+ * and returns a pointer to it. If the class has no registered factory
+ * function a null pointer is returned.
+ *
+ * \sa registerLayout(), unregisterLayout(), registeredLayouts()
+ */
+ static Layout *createLayout(const QString &rLayoutClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static Layout *createLayout(const char *pLayoutClassName);
+
+ /*!
+ * Returns the Factory instance.
+ */
+ static Factory *instance();
+
+ /*!
+ * Registers the Appender factory function \a pAppenderFactoryFunc
+ * for the class \a rAppenderClassName. If a registered factory
+ * function exists for the class, it is replaced with
+ * \a pAppenderFactoryFunc.
+ *
+ * \sa unregisterAppender(), registeredAppenders(), createAppender()
+ */
+ static void registerAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void registerAppender(const char *pAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc);
+
+ /*!
+ * Registers the Filter factory function \a pFilterFactoryFunc
+ * for the class \a rFilterClassName. If a registered factory
+ * function exists for the class, it is replaced with
+ * \a pFilterFactoryFunc.
+ *
+ * \sa unregisterFilter(), registeredFilters(), createFilter()
+ */
+ static void registerFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void registerFilter(const char *pFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc);
+
+ /*!
+ * Registers the Layout factory function \a pLayoutFactoryFunc
+ * for the class \a rLayoutClassName. If a registered factory
+ * function exists for the class, it is replaced with
+ * \a pLayoutFactoryFunc.
+ *
+ * \sa unregisterLayout(), registeredLayout(), createLayout()
+ */
+ static void registerLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void registerLayout(const char *pLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc);
+
+ /*!
+ * Returns a list of the class names for registered Appender factory
+ * functions.
+ *
+ * \sa registerAppender(), unregisterAppender()
+ */
+ static QStringList registeredAppenders();
+
+ /*!
+ * Returns a list of the class names for registered Filter factory
+ * functions.
+ *
+ * \sa registerFilter(), unregisterFilter()
+ */
+ static QStringList registeredFilters();
+
+ /*!
+ * Returns a list of the class names for registered Layout factory
+ * functions.
+ *
+ * \sa registerLayout(), unregisterLayout()
+ */
+ static QStringList registeredLayouts();
+
+ /*!
+ * Sets the property \a rProperty of the object \a pObject to the
+ * value \a rValue. The function will test that the property
+ * \a rProperty is writeable and of a type the function can convert to.
+ * The types bool, int, Level and QString are supported.
+ *
+ * \sa OptionConverter
+ */
+ static void setObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void setObjectProperty(QObject *pObject,
+ const char *pProperty,
+ const QString &rValue);
+
+ /*!
+ * Unregisters the Appender factory function for the class
+ * \a rAppenderClassName.
+ *
+ * \sa registerAppender(), registeredAppenders()
+ */
+ static void unregisterAppender(const QString &rAppenderClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void unregisterAppender(const char *pAppenderClassName);
+
+ /*!
+ * Unregisters the Filter factory function for the class
+ * \a rFilterClassName.
+ *
+ * \sa registerFilter(), registeredFilters()
+ */
+ static void unregisterFilter(const QString &rFilterClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void unregisterFilter(const char *pFilterClassName);
+
+ /*!
+ * Unregisters the Layout factory function for the class
+ * \a rLayoutClassName.
+ *
+ * \sa registerLayout(), registeredLayouts()
+ */
+ static void unregisterLayout(const QString &rLayoutClassName);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ static void unregisterLayout(const char *pLayoutClassName);
+
+ private:
+ Appender *doCreateAppender(const QString &rAppenderClassName);
+ Filter *doCreateFilter(const QString &rFilterClassName);
+ Layout *doCreateLayout(const QString &rLayoutClassName);
+ void doRegisterAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc);
+ void doRegisterFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc);
+ void doRegisterLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc);
+ void doSetObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue);
+ void doUnregisterAppender(const QString &rAppenderClassName);
+ void doUnregisterFilter(const QString &rFilterClassName);
+ void doUnregisterLayout(const QString &rLayoutClassName);
+ void registerDefaultAppenders();
+ void registerDefaultFilters();
+ void registerDefaultLayouts();
+ bool validateObjectProperty(QMetaProperty &rMetaProperty,
+ const QString &rProperty,
+ QObject *pObject);
+
+ private:
+ mutable QMutex mObjectGuard;
+ QHash<QString, AppenderFactoryFunc> mAppenderRegistry;
+ QHash<QString, FilterFactoryFunc> mFilterRegistry;
+ QHash<QString, LayoutFactoryFunc> mLayoutRegistry;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates Factory
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %Factory(appenderfactories:("Log4Qt::DebugAppender", "Log4Qt::NullAppender",
+ * "Log4Qt::ConsoleAppender", "org.apache.log4j.varia.DebugAppender",
+ * "org.apache.log4j.FileAppender", "org.apache.log4j.RollingFileAppender",
+ * "org.apache.log4j.DailyRollingFileAppender",
+ * "org.apache.log4j.varia.ListAppender",
+ * "org.apache.log4j.varia.NullAppender",
+ * "Log4Qt::FileAppender", "org.apache.log4j.ConsoleAppender",
+ * "Log4Qt::DailyRollingFileAppender", "Log4Qt::ListAppender",
+ * "Log4Qt::RollingFileAppender") filterfactories:
+ * ("Log4Qt::DenyAllFilter", "Log4Qt::StringMatchFilter",
+ * "Log4Qt::LevelRangeFilter", "org.apache.log4j.varia.DenyAllFilter",
+ * "org.apache.log4j.varia.LevelRangeFilter",
+ * "org.apache.log4j.varia.StringMatchFilter", "Log4Qt::LevelMatchFilter",
+ * "org.apache.log4j.varia.LevelMatchFilter") layoutfactories:
+ * ("org.apache.log4j.SimpleLayout", "Log4Qt::PatternLayout",
+ * "Log4Qt::SimpleLayout", "org.apache.log4j.TTCCLayout",
+ * "Log4Qt::TTCCLayout", "org.apache.log4j.PatternLayout") )
+ * </tt>
+ * \sa QDebug, Factory::logManager()
+ */
+ QDebug operator<<(QDebug debug,
+ const Factory &rFactory);
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Appender *Factory::createAppender(const QString &rAppenderClassName)
+ { return instance()->doCreateAppender(rAppenderClassName); }
+
+ inline Appender *Factory::createAppender(const char *pAppenderClassName)
+ { return instance()->doCreateAppender(QLatin1String(pAppenderClassName)); }
+
+ inline Filter *Factory::createFilter(const QString &rFilterClassName)
+ { return instance()->doCreateFilter(rFilterClassName); }
+
+ inline Filter *Factory::createFilter(const char *pFilterClassName)
+ { return instance()->doCreateFilter(QLatin1String(pFilterClassName)); }
+
+ inline Layout *Factory::createLayout(const QString &rLayoutClassName)
+ { return instance()->doCreateLayout(rLayoutClassName); }
+
+ inline Layout *Factory::createLayout(const char *pLayoutClassName)
+ { return instance()->doCreateLayout(QLatin1String(pLayoutClassName)); }
+
+ inline void Factory::registerAppender(const QString &rAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc)
+ { instance()->doRegisterAppender(rAppenderClassName, pAppenderFactoryFunc); }
+
+ inline void Factory::registerAppender(const char *pAppenderClassName,
+ AppenderFactoryFunc pAppenderFactoryFunc)
+ { instance()->doRegisterAppender(QLatin1String(pAppenderClassName), pAppenderFactoryFunc); }
+
+ inline void Factory::registerFilter(const QString &rFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc)
+ { instance()->doRegisterFilter(rFilterClassName, pFilterFactoryFunc); }
+
+ inline void Factory::registerFilter(const char *pFilterClassName,
+ FilterFactoryFunc pFilterFactoryFunc)
+ { instance()->doRegisterFilter(QLatin1String(pFilterClassName), pFilterFactoryFunc); }
+
+ inline void Factory::registerLayout(const QString &rLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc)
+ { instance()->doRegisterLayout(rLayoutClassName, pLayoutFactoryFunc); }
+
+ inline void Factory::registerLayout(const char *pLayoutClassName,
+ LayoutFactoryFunc pLayoutFactoryFunc)
+ { instance()->doRegisterLayout(QLatin1String(pLayoutClassName), pLayoutFactoryFunc); }
+
+ inline QStringList Factory::registeredAppenders()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mAppenderRegistry.keys(); }
+
+ inline QStringList Factory::registeredFilters()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mFilterRegistry.keys(); }
+
+ inline QStringList Factory::registeredLayouts()
+ { QMutexLocker locker(&instance()->mObjectGuard);
+ return instance()->mLayoutRegistry.keys(); }
+
+ inline void Factory::setObjectProperty(QObject *pObject,
+ const QString &rProperty,
+ const QString &rValue)
+ { instance()->doSetObjectProperty(pObject, rProperty, rValue); }
+
+ inline void Factory::setObjectProperty(QObject *pObject,
+ const char *pProperty,
+ const QString &rValue)
+ { instance()->doSetObjectProperty(pObject, QLatin1String(pProperty), rValue); }
+
+ inline void Factory::unregisterAppender(const QString &rAppenderClassName)
+ { instance()->doUnregisterAppender(rAppenderClassName); }
+
+ inline void Factory::unregisterAppender(const char *pAppenderClassName)
+ { instance()->doUnregisterAppender(QLatin1String(pAppenderClassName)); }
+
+ inline void Factory::unregisterFilter(const QString &rFilterClassName)
+ { instance()->doUnregisterFilter(rFilterClassName); }
+
+ inline void Factory::unregisterFilter(const char *pFilterClassName)
+ { instance()->doUnregisterFilter(QLatin1String(pFilterClassName)); }
+
+ inline void Factory::unregisterLayout(const QString &rLayoutClassName)
+ { instance()->doUnregisterLayout(rLayoutClassName); }
+
+ inline void Factory::unregisterLayout(const char *pLayoutClassName)
+ { instance()->doUnregisterLayout(QLatin1String(pLayoutClassName)); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::Factory, Q_COMPLEX_TYPE); // use default
+
+
+#endif // LOG4QT_HELPERS_FACTORY_H
diff --git a/ext/Log4Qt/src/helpers/initialisationhelper.cpp b/ext/Log4Qt/src/helpers/initialisationhelper.cpp
new file mode 100755
index 0000000..c2d72a8
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/initialisationhelper.cpp
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: initialisationhelper.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 "helpers/initialisationhelper.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QMutex>
+#include <QtCore/QProcess>
+#include <QtCore/QSettings>
+#include "helpers/datetime.h"
+#include "helpers/logerror.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: InitialisationHelper
+ **************************************************************************/
+
+
+ InitialisationHelper::InitialisationHelper() :
+ mStartTime(DateTime::currentDateTime().toMilliSeconds()),
+ mEnvironmentSettings()
+ {
+ doRegisterTypes();
+ doInitialiseEnvironmentSettings();
+ }
+
+
+ InitialisationHelper::~InitialisationHelper()
+ {
+ Q_ASSERT_X(false, "InitialisationHelper::~InitialisationHelper()", "Unexpected destruction of singleton object");
+ }
+
+
+ LOG4QT_IMPLEMENT_INSTANCE(InitialisationHelper)
+
+
+ void InitialisationHelper::doInitialiseEnvironmentSettings()
+ {
+ // Is Process::systemEnvironment() safe to be used before a QCoreApplication
+ // object has been created?
+
+ QStringList setting_keys;
+ setting_keys << QLatin1String("Debug");
+ setting_keys << QLatin1String("DefaultInitOverride");
+ setting_keys << QLatin1String("Configuration");
+ setting_keys << QLatin1String("ConfiguratorClass");
+
+ QHash<QString, QString> env_keys;
+ QString entry;
+ Q_FOREACH(entry, setting_keys)
+ env_keys.insert(QString::fromLatin1("log4qt_").append(entry).toUpper(), entry);
+
+ QStringList sys_env = QProcess::systemEnvironment();
+ Q_FOREACH(entry, sys_env)
+ {
+ int i = entry.indexOf(QLatin1Char('='));
+ if (i == -1)
+ continue;
+ QString key = entry.left(i);
+ QString value = entry.mid(i + 1).trimmed();
+ if (env_keys.contains(key))
+ mEnvironmentSettings.insert(env_keys.value(key), value);
+ }
+ }
+
+
+ void InitialisationHelper::doRegisterTypes()
+ {
+ qRegisterMetaType<Log4Qt::LogError>("Log4Qt::LogError");
+ qRegisterMetaType<Log4Qt::Level>("Log4Qt::Level");
+ qRegisterMetaType<Log4Qt::LoggingEvent>("Log4Qt::LoggingEvent");
+
+#ifndef QT_NO_DATASTREAM
+ qRegisterMetaTypeStreamOperators<Log4Qt::LogError>("Log4Qt::LogError");
+ qRegisterMetaTypeStreamOperators<Log4Qt::Level>("Log4Qt::Level");
+ qRegisterMetaTypeStreamOperators<LoggingEvent>("Log4Qt::LoggingEvent");
+#endif
+ }
+
+
+ QString InitialisationHelper::doSetting(const QString &rKey,
+ const QString &rDefault) const
+ {
+ if (mEnvironmentSettings.contains(rKey))
+ return mEnvironmentSettings.value(rKey);
+
+ if (QCoreApplication::instance())
+ {
+ QSettings s;
+ s.beginGroup(QLatin1String("Log4Qt"));
+ return s.value(rKey, rDefault).toString().trimmed();
+ }
+ else
+ return rDefault;
+ }
+
+
+ bool InitialisationHelper::staticInitialisation()
+ {
+ instance();
+ return true;
+ }
+
+
+ bool InitialisationHelper::msStaticInitialisation = staticInitialisation();
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const InitialisationHelper &rInitialisationHelper)
+ {
+ Q_UNUSED(rInitialisationHelper);
+ debug.nospace() << "InitialisationHelper("
+ << "starttime:" << InitialisationHelper::startTime()
+ << "(" << DateTime::fromMilliSeconds(InitialisationHelper::startTime()) << ")"
+ << "environmentsettings:" << InitialisationHelper::environmentSettings()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/initialisationhelper.h b/ext/Log4Qt/src/helpers/initialisationhelper.h
new file mode 100755
index 0000000..ea508da
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/initialisationhelper.h
@@ -0,0 +1,435 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: initialisationhelper.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_test_and_set_ptr with
+ * QBasicAtomicPointer
+ *
+ *
+ * Copyright 2007 - 2008 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_HELPERS_INITIALISATIONHELPER_H
+#define LOG4QT_HELPERS_INITIALISATIONHELPER_H
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QAtomicPointer>
+#include <QtCore/QHash>
+#include <QString>
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# ifndef Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
+# warning "QAtomicPointer test and set is not native. The macros Log4Qt::LOG4QT_GLOBAL_STATIC and Log4Qt::LOG4QT_IMPLEMENT_INSTANCE are not thread-safe."
+# endif
+#endif
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QMutex;
+
+namespace Log4Qt
+{
+ /*!
+ * LOG4QT_GLOBAL_STATIC declares a static function \a FUNCTION that
+ * returns a pointer to a singleton object of the type \a TYPE.
+ *
+ * The macro uses a static variable to store a pointer to the singleton
+ * object. On the first invocation an object of the type \a TYPE is created
+ * on the heap and the pointer is set. Any further invocations will return
+ * the stored pointer. If multiple threads are accessing the function
+ * without the pointer being set, each thread will create an object of the
+ * type \a TYPE. The threads that find the pointer already been set will
+ * delete their object. The singleton object will not be deleted during static
+ * de-initialisation.
+ *
+ * The following example uses a global global mutex object to synchronise
+ * access to a static member variable.
+ *
+ * \code
+ * #file: myclass.h
+ *
+ * class MyClass
+ * {
+ * public:
+ * MyClass();
+ * ~MyClass();
+ * private:
+ * static qint64 msObjectCount;
+ * }
+ * \endcode
+ * \code
+ * #file: myclass.cpp
+ *
+ * #include myclass.h
+ *
+ * LOG4QT_GLOBAL_STATIC(QMutex, class_guard)
+ *
+ * MyClass::MyClass()
+ * {
+ * QMutexLocker(class_guard());
+ * msObjectCount++;
+ * }
+ *
+ * MyClass::~MyClass()
+ * {
+ * QMutexLocker(class_guard());
+ * msObjectCount--;
+ * }
+ *
+ * qint64 MyClass::msObjectCount = 0;
+ * \endcode
+ *
+ * \note The function created by the macro is thread-safe.
+ *
+ * \sa \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE",
+ * \ref Log4Qt::InitialisationHelper "InitialisationHelper"
+ */
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
+ static volatile TYPE *sp_global_static_##FUNCTION = 0; \
+ TYPE *FUNCTION() \
+ { \
+ if (!sp_global_static_##FUNCTION) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!q_atomic_test_and_set_ptr(&sp_global_static_##FUNCTION, \
+ 0, p_temp)) \
+ delete p_temp; \
+ } \
+ return const_cast<TYPE *>(sp_global_static_##FUNCTION); \
+ }
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
+ static QBasicAtomicPointer<TYPE > sp_global_static_##FUNCTION = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *FUNCTION() \
+ { \
+ if (!sp_global_static_##FUNCTION) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \
+ p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_global_static_##FUNCTION; \
+ }
+#else
+ #define LOG4QT_GLOBAL_STATIC(TYPE, FUNCTION) \
+ static QBasicAtomicPointer<TYPE > sp_global_static_##FUNCTION = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *FUNCTION() \
+ { \
+ if (!sp_global_static_##FUNCTION.loadAcquire()) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_global_static_##FUNCTION.testAndSetOrdered(0, \
+ p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_global_static_##FUNCTION.loadAcquire(); \
+ }
+#endif
+
+ /*!
+ * LOG4QT_IMPLEMENT_INSTANCE implements an instance function for a
+ * singleton class \a TYPE.
+ *
+ * The function works like the one created by
+ * \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC".
+ *
+ * The following example illustrates how to use the macro to create a
+ * singleton class:
+ *
+ * \code
+ * #file: mysingleton.h
+ *
+ * class MySingleton
+ * {
+ * private:
+ * MySingleton();
+ * ~MySingleton();
+ * public:
+ * MySingleton *instance();
+ * }
+ * \endcode
+ * \code
+ * #file: mysingleton.cpp
+ *
+ * #include mysingleton.h
+ *
+ * MySingleton::MySingleton()
+ * {}
+ *
+ * MySingleton::~MySingleton()
+ * {}
+ *
+ * LOG4QT_IMPLEMENT_INSTANCE(MySingleton)
+ *
+ * \endcode
+ *
+ * \note The function created by the macro is thread-safe.
+ *
+ * \sa \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC",
+ * \ref Log4Qt::InitialisationHelper "InitialisationHelper"
+ */
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
+ static TYPE *sp_singleton_##TYPE = 0; \
+ TYPE *TYPE::instance() \
+ { \
+ if (!sp_singleton_##TYPE) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!q_atomic_test_and_set_ptr(&sp_singleton_##TYPE, \
+ 0, p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_singleton_##TYPE; \
+ }
+#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
+ static QBasicAtomicPointer<TYPE > sp_singleton_##TYPE = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *TYPE::instance() \
+ { \
+ if (!sp_singleton_##TYPE) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_singleton_##TYPE; \
+ }
+#else
+ #define LOG4QT_IMPLEMENT_INSTANCE(TYPE) \
+ static QBasicAtomicPointer<TYPE > sp_singleton_##TYPE = \
+ Q_BASIC_ATOMIC_INITIALIZER(0); \
+ TYPE *TYPE::instance() \
+ { \
+ if (!sp_singleton_##TYPE.loadAcquire()) \
+ { \
+ TYPE *p_temp = new TYPE; \
+ if (!sp_singleton_##TYPE.testAndSetOrdered(0, p_temp)) \
+ delete p_temp; \
+ } \
+ return sp_singleton_##TYPE.loadAcquire(); \
+ }
+#endif
+
+ /*!
+ * \brief The class InitialisationHelper performs static initialisation
+ * tasks.
+ *
+ * The InitialisationHelper is either created on the first call or through
+ * static initialisation. It will capture the programs startup time,
+ * which can be retrieved using startTime(). The system environment
+ * is analysed for package related definitions. The result is available
+ * over environmentSettings(). The packages custom types are registered with
+ * the Qt type system.
+ *
+ * Settings for the package can be retrieved using setting(). Two macros
+ * are available to help with the creation of singletons / global static
+ * objects (\ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" and
+ * \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE").
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa \ref Init "Initialization procedure",
+ */
+ class LOG4QT_EXPORT InitialisationHelper
+ {
+ private:
+ InitialisationHelper();
+ InitialisationHelper(const InitialisationHelper &rOther); // Not implemented
+ virtual ~InitialisationHelper();
+ InitialisationHelper &operator=(const InitialisationHelper &rOther); // Not implemented
+
+ public:
+
+ /*!
+ * Returns a hash with the settings retrieved from the system
+ * environment on startup.
+ *
+ * The following table shows the environment variables taken into
+ * account and the setting key used for them.
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="25%"> Environment variable </th>
+ * <th width="25%"> Setting key </th>
+ * </tr><tr>
+ * <td> LOG4QT_DEBUG </td>
+ * <td> Debug </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> LOG4QT_DEFAULTINITOVERRIDE </td>
+ * <td> DefaultInitOverride </td>
+ * </tr><tr>
+ * <td> LOG4QT_CONFIGURATION </td>
+ * <td> Configuration </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> LOG4QT_CONFIGURATORCLASS </td>
+ * <td> ConfiguratorClass </td>
+ * </tr>
+ * </table>
+ *
+ * \sa \ref Env "Environment Variables",
+ * setting()
+ */
+ static QHash<QString, QString> environmentSettings();
+
+ /*!
+ * Returns the InitialisationHelper instance.
+ */
+ static InitialisationHelper *instance();
+
+ /*!
+ * Returns the value for the setting \a rKey or \a rDefault, if it is
+ * not defined.
+ *
+ * A setting can be either defined by an environment variable or by a
+ * key in the application setting. The function will first test the
+ * settings made by environment variables for the key \a rKey using
+ * environmentSettings(). If the key is not present and a
+ * QCoreApplication exists, the application settings are tested for
+ * the key \a rKey in the group \c %Log4Qt.
+ *
+ * The following setting exists:
+ *
+ * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7">
+ * <tr bgcolor="#d5e1e8">
+ * <th width="25%"> Setting key </th>
+ * <th> Description </th>
+ * </tr><tr>
+ * <td> Debug </td>
+ * <td> The variable controls the Level value for the logger
+ * LogManager::logLogger(). If the value is a valid Level string,
+ * the level for the logger is set to the level. If the value is not
+ * a valid Level string, \ref Level::DEBUG_INT "DEBUG_INT" is used.
+ * Otherwise \ref Level::ERROR_INT "ERROR_INT" is used. </td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> DefaultInitOverride </td>
+ * <td> The variable controls the \ref Init "initialization procedure"
+ * performed by the \ref LogManager "LogManager" on startup.
+ * If it is set to any other value then \c false the \ref Init
+ * "initialization procedure" is skipped.</td>
+ * </tr><tr>
+ * <td> Configuration </td>
+ * <td> Specifies the configuration file used for initialising the package.</td>
+ * </tr><tr bgcolor="#ffffff">
+ * <td> ConfiguratorClass </td>
+ * <td> Specifies the configurator class used for initialising the package.</td>
+ * </tr>
+ * </table>
+ *
+ * \sa environmentSettings(), \ref Env "Environment Variables",
+ * \ref Init "Initialization procedure",
+ * LogManager::configureLogLogger(), LogManager::startup()
+ */
+ static QString setting(const QString &rKey,
+ const QString &rDefault = QString());
+
+ /*!
+ * Returns the start time of the program as the number of milliseconds
+ * that have passed since 1970-01-01T00:00:00,000, Coordinated
+ * Universal Time (Qt::UTC).
+ *
+ * \sa DateTime::fromMilliSeconds(),
+ * DateTime::toMilliSeconds()
+ */
+ static qint64 startTime();
+
+ private:
+ void doInitialiseEnvironmentSettings();
+ void doRegisterTypes();
+ QString doSetting(const QString &rKey,
+ const QString &rDefault) const;
+ static bool shutdown();
+ static bool staticInitialisation();
+
+ private:
+ // QMutex mObjectGuard;
+ const qint64 mStartTime;
+ QHash <QString, QString> mEnvironmentSettings;
+ static bool msStaticInitialisation;
+
+#ifndef QT_NO_DEBUG_STREAM
+ // Needs to be friend to access details
+ friend QDebug operator<<(QDebug debug,
+ const InitialisationHelper &rInitialisationHelper);
+#endif // QT_NO_DEBUG_STREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates InitialisationHelper
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %InitialisationHelper(InitialisationHelper(starttime:1193883677438(
+ * QDateTime("Wed Oct 31 21:21:17 2007") )
+ * environmentsettings: QHash(("configuration", "\myapp.log4j")
+ * ("Debug", "DEBUG")) ) )
+ * </tt>
+ * \sa QDebug, InitialisationHelper::logManager()
+ */
+ QDebug operator<<(QDebug debug,
+ const InitialisationHelper &rInitialisationHelper);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline QHash<QString, QString> InitialisationHelper::environmentSettings()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return instance()->mEnvironmentSettings; }
+
+ inline QString InitialisationHelper::setting(const QString &rKey,
+ const QString &rDefault)
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Reentrant and const
+ return instance()->doSetting(rKey, rDefault); }
+
+ inline qint64 InitialisationHelper::startTime()
+ { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime
+ return instance()->mStartTime; }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::InitialisationHelper, Q_COMPLEX_TYPE); // use default
+
+
+#endif // LOG4QT_HELPERS_INITIALISATIONHELPER_H
diff --git a/ext/Log4Qt/src/helpers/logerror.cpp b/ext/Log4Qt/src/helpers/logerror.cpp
new file mode 100755
index 0000000..1bf8030
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logerror.cpp
@@ -0,0 +1,352 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logerror.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/logerror.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QByteArray>
+#include <QtCore/QDataStream>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QTextCodec>
+#include <QtCore/QThreadStorage>
+#include "helpers/initialisationhelper.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+ typedef QThreadStorage<LogError *> ThreadError;
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_GLOBAL_STATIC(ThreadError, thread_error)
+
+
+
+ /**************************************************************************
+ * Class implementation: LogError
+ **************************************************************************/
+
+
+ LogError::LogError() :
+ mCode(0),
+ mContext(),
+ mMessage(),
+ mSymbol(),
+ mArgs(),
+ mCausingErrors()
+ {
+ }
+
+
+ LogError::LogError(const QString &rMessage,
+ int code,
+ const QString &rSymbol,
+ const QString &rContext) :
+ mCode(code),
+ mContext(rContext),
+ mMessage(cleanMessage(rMessage)),
+ mSymbol(rSymbol),
+ mArgs(),
+ mCausingErrors()
+ {
+ }
+
+
+ LogError::LogError(const char *pMessage,
+ int code,
+ const char *pSymbol,
+ const char *pContext,
+ Encoding encoding) :
+ mCode(code),
+ mContext(QString::fromLatin1(pContext)),
+ mMessage(),
+ mSymbol(QString::fromLatin1(pSymbol)),
+ mArgs(),
+ mCausingErrors()
+ {
+ switch(encoding)
+ {
+ case LATIN1:
+ mMessage = QString::fromLatin1(pMessage);
+ break;
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ case CODECFORTR:
+ mMessage = QTextCodec::codecForTr()->toUnicode(pMessage);
+ break;
+#endif
+ case UNICODEUTF8:
+ mMessage = QString::fromUtf8(pMessage);
+ break;
+ default:
+ Q_ASSERT_X(false, "LogError::LogError", "Unkown encoding constant");
+ mMessage = QString::fromLatin1(pMessage);
+ }
+ mMessage = cleanMessage(mMessage);
+
+ if (mSymbol == QString::number(mCode))
+ mSymbol.clear();
+ }
+
+
+ QString LogError::translatedMessage() const
+ {
+ return QCoreApplication::translate(mContext.toLatin1(), mMessage.toUtf8().data(), 0
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ , QCoreApplication::UnicodeUTF8
+#endif
+ );
+ }
+
+
+ LogError LogError::lastError()
+ {
+ if (!thread_error()->hasLocalData())
+ return LogError();
+ else
+ return *thread_error()->localData();
+ }
+
+
+ void LogError::setLastError(const LogError &rLogError)
+ {
+ if (!thread_error()->hasLocalData())
+ thread_error()->setLocalData(new LogError);
+
+ *thread_error()->localData() = rLogError;
+ }
+
+
+ QString LogError::toString() const
+ {
+ QString result = messageWithArgs();
+
+ QString context_symbol = mContext;
+ if (!context_symbol.isEmpty() && !mSymbol.isEmpty())
+ context_symbol.append(QLatin1String("::"));
+ context_symbol.append(mSymbol);
+
+ if (!context_symbol.isEmpty() || mCode)
+ {
+ result.append(QLatin1String(" ("));
+ if (!context_symbol.isEmpty())
+ result.append(context_symbol);
+ if (!context_symbol.isEmpty() && mCode)
+ result.append(QLatin1String(", "));
+ if (mCode)
+ result.append(QString::number(mCode));
+ result.append(QLatin1String(")"));
+ }
+
+ if (!mCausingErrors.isEmpty())
+ {
+ QString causing_errors_str = QLatin1String(": ") + mCausingErrors.at(0).toString();
+ int i = 1;
+ while (i < mCausingErrors.count())
+ {
+ causing_errors_str.append(QLatin1String(", ")).append(mCausingErrors.at(i).toString());
+ i++;
+ }
+ result.append(causing_errors_str);
+ }
+
+ return result;
+ }
+
+
+ QString LogError::insertArgs(const QString &rMessage) const
+ {
+ QString result;
+
+ /*
+
+ // Don't use a loop to be able to handle arguments that conatin strings
+ // like %1.
+ // Using this method only 9 arguments can be handled as the %1
+ // in %11 gets also replaced with the first argument.
+
+ switch (mArgs.count())
+ {
+ case 0:
+ break;
+ case 1:
+ result = rMessage.arg(mArgs.at(0));
+ break;
+ case 2:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1));
+ break;
+ case 3:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2));
+ break;
+ case 4:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3));
+ break;
+ case 5:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4));
+ break;
+ case 6:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5));
+ break;
+ case 7:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6));
+ break;
+ case 8:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7));
+ break;
+ default:
+ result = rMessage.arg(mArgs.at(0), mArgs.at(1), mArgs.at(2), mArgs.at(3), mArgs.at(4), mArgs.at(5), mArgs.at(6), mArgs.at(7), mArgs.at(8));
+ break;
+ }
+
+ if (mArgs.count() > 9)
+ {
+ int i = 9;
+ while(i < mArgs.count())
+ {
+ result = result.arg(mArgs.at(i));
+ i++;
+ }
+ }
+ */
+
+ result = rMessage;
+ QVariant arg;
+ Q_FOREACH(arg, mArgs)
+ result = result.arg(arg.toString());
+ return result;
+ }
+
+
+ QString LogError::cleanMessage(const QString &rMessage)
+ {
+ if (rMessage.isEmpty())
+ return rMessage;
+
+ QString result = rMessage;
+ if (rMessage.at(rMessage.size() - 1) == QLatin1Char('.'))
+ result = rMessage.left(rMessage.size() - 1);
+ return result;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DATASTREAM
+ QDataStream &operator<<(QDataStream &rStream,
+ const LogError &rLogError)
+ {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream stream(&buffer);
+
+ // version
+ quint16 version = 0;
+ stream << version;
+ // version 0 data
+ stream << rLogError.mCode
+ << rLogError.mContext
+ << rLogError.mMessage
+ << rLogError.mSymbol
+ << rLogError.mArgs
+ << rLogError.mCausingErrors;
+
+ buffer.close();
+ rStream << buffer.buffer();
+ return rStream;
+ }
+
+
+ QDataStream &operator>>(QDataStream &rStream,
+ LogError &rLogError)
+ {
+ QByteArray array;
+ rStream >> array;
+ QBuffer buffer(&array);
+ buffer.open(QIODevice::ReadOnly);
+ QDataStream stream(&buffer);
+
+ // version
+ quint16 version;
+ stream >> version;
+ // Version 0 data
+ QString level;
+ QString logger;
+ stream >> rLogError.mCode
+ >> rLogError.mContext
+ >> rLogError.mMessage
+ >> rLogError.mSymbol
+ >> rLogError.mArgs
+ >> rLogError.mCausingErrors;
+
+ buffer.close();
+ return rStream;
+ }
+#endif // QT_NO_DATASTREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const LogError &rLogError)
+ {
+ // Escape % sign
+ QString message = rLogError.message();
+ message.replace(QLatin1String("%"), QLatin1String("%%"));
+
+ debug.nospace() << "LogError("
+ << "code:" << rLogError.code() << " "
+ << "context:" << rLogError.context() << " "
+ << "message:" << message << " "
+ << "symbol:" << rLogError.symbol() << " "
+ << "args:" << rLogError.args()
+ << "translatedMessage:" << rLogError.translatedMessage()
+ << ")";
+ return debug.maybeSpace();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/logerror.h b/ext/Log4Qt/src/helpers/logerror.h
new file mode 100755
index 0000000..4ea7cfe
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logerror.h
@@ -0,0 +1,550 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logerror.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGERROR_H
+#define LOG4QT_LOGERROR_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+namespace Log4Qt
+{
+ /*!
+ * Creates an LogError object with the error message \a message, the error
+ * code \a code and the context \a context. The symbol of the error is
+ * set to \a code as string value.
+ *
+ * The following example logs an error, if a character is not a digit.
+ *
+ * \code
+ * if (!c.isDigit())
+ * {
+ * Error e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."),
+ * LAYOUT_EXPECTED_DIGIT_ERROR,
+ * "Log4Qt::PatternFormatter");
+ * e << QString(c);
+ * logger()->error(e);
+ * }
+ * \endcode
+ */
+ #define LOG4QT_ERROR(message, code, context) \
+ LogError(message, code, #code, context)
+
+ /*!
+ * Creates an LogError object with the error message \a message and the
+ * error code \a code. The symbol of the error is set to \a code as string
+ * value. The context is set to the class name of the current object. The
+ * current objects class must be derived from QObject.
+ *
+ * The following example handles an error while opening a file.
+ *
+ * \code
+ * if (!mpFile->open(mode))
+ * {
+ * LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to open file '%1' for appender '%2'"),
+ * APPENDER_OPENING_FILE_ERROR);
+ * e << mFileName << name();
+ * e.addCausingError(LogError(mpFile->errorString(), mpFile->error()));
+ * logger()->error(e);
+ * return;
+ * }
+ * \endcode
+ */
+ #define LOG4QT_QCLASS_ERROR(message, code) \
+ LogError(message, code, #code, this->metaObject()->className())
+
+ /*!
+ * \brief The class LogError represents an error.
+ *
+ * The class error allows storing error information in a structured way.
+ * The error message is stored separately from the information that may be
+ * substituted into the message string. This way it is possible to access
+ * all information after the error has been raised. It also allows to
+ * translate the error at a later point in time or to get a translated and
+ * a not translated error text (e.g. translated for the UI and not
+ * translated for a log).
+ *
+ * The message is accessed using message() and setMessage(). Arguments for
+ * the message can be added using addArg() or operator<<(). The arguments
+ * can be retrieved using args(). The message with substituted arguments
+ * is returned by messageWithArgs().
+ *
+ * An error code can be set as integer value code() and/or a symbolic value
+ * symbol().
+ *
+ * To allow the translation of the message the error stores the translation
+ * context (context(), setContext()). The translated message can be accessed
+ * using translatedMessage() or using translatedMessageWithArgs(), if it
+ * should contain the arguments.
+ *
+ * An error can have one or more related errors that caused it. An error is
+ * related using addCausingError(). All causing errors can be retrieved using
+ * causingErrors().
+ *
+ * A per thread error can be maintained using lastError() and setLastError().
+ *
+ * There are two macros avaiable to simplify the error creation. The macro
+ * \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR" is used with classes not derived
+ * from QObject. The macro \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR"
+ * is used with classes derived from QObject.
+ */
+ class LOG4QT_EXPORT LogError
+ {
+ public:
+
+ /*!
+ * The enum Encoding defines the 8-bit encoding of a character string
+ * arguments to \ref LogError::LogError(const char *, int, const char *,
+ * const char *, Encoding) "LogError::LogError()".
+ *
+ * \sa \ref LogError::LogError(const char *, int, const char *, const char *, Encoding) "LogError::LogError()"
+ */
+ enum Encoding
+ {
+ /*! LATIN-1 */
+ LATIN1,
+ /*!
+ * The encoding specified by QTextCodec::codecForTr()
+ * (Latin-1 if none has been set).
+ */
+ CODECFORTR,
+ /*! UTF-8 */
+ UNICODEUTF8
+ };
+ //Q_ENUMS(Encoding)
+
+ /*!
+ * Creates an empty error. The error code is set to 0 and all other
+ * members are set to be empty.
+ *
+ * \sa isEmpty()
+ */
+ LogError();
+
+ /*!
+ * Creates an error with the Message \a rMessage and the error code
+ * \a code. The symbol for the error code is set to \a rSymbol and the
+ * context to \a rContext.
+ *
+ * \a rContext must be string that can be converted to Latin-1. The
+ * Latin-1 representation of the string is used with
+ * QApplication::translate(), if a translation for \a rMessage is
+ * requested.
+ *
+ * \sa translatedMessage(), translatedMessageWithArgs()
+ */
+ LogError(const QString &rMessage,
+ int code = 0,
+ const QString &rSymbol = QString(),
+ const QString &rContext = QString());
+
+ /*!
+ * Creates an error with the Message \a pMessage and the error code
+ * \a code. The symbol for the error code is set to \a pSymbol and the
+ * context to \a pContext.
+ *
+ * \a encoding specifies the encoding of \a pMessage. \a pSymbol and
+ * \a pContext are expected to be Latin-1.
+ *
+ * \note To support the macros \ref Log4Qt::LOG4QT_ERROR "LOG4QT_ERROR"
+ * and \ref Log4Qt::LOG4QT_QCLASS_ERROR "LOG4QT_QCLASS_ERROR"
+ * the function tests, if \a pSymbol is the string representation of
+ * \a code. If it is, the symbol is set to be empty. Otherwise symbol
+ * is set to \a pSymbol.
+ *
+ * \sa translatedMessage(), translatedMessageWithArgs()
+ */
+ LogError(const char *pMessage,
+ int code = 0,
+ const char *pSymbol = 0,
+ const char *pContext = 0,
+ Encoding encoding = LATIN1);
+
+ // LogError(const LogError &rOther); // Use compiler default
+ // virtual ~LogError(); // Use compiler default
+ // LogError &operator=(const LogError &rOther); // Use compiler default
+
+ /*!
+ * Returns the error code.
+ *
+ * \sa setCode()
+ */
+ int code() const;
+
+ /*!
+ * Returns the context for the error.
+ *
+ * \sa setContext()
+ */
+ QString context() const;
+
+ /*!
+ * Returns the error message.
+ *
+ * \sa setMessage()
+ */
+ QString message() const;
+
+ /*!
+ * Returns the symbol for the error code.
+ *
+ * \sa setSymbol()
+ */
+ QString symbol() const;
+
+ /*!
+ * Returns the translated error message.
+ *
+ * The translated message is created by calling
+ * QCoreApplication::translate() using context().toLatin1() as
+ * context and message.toUtf8() as message.
+ *
+ * \sa translatedMessageWithArgs()
+ */
+ QString translatedMessage() const;
+
+ /*!
+ * Sets the error code to \a code.
+ *
+ * \sa code()
+ */
+ void setCode(int code);
+
+ /*!
+ * Sets the context to \a rClassName.
+ *
+ * \a rContext must be string that can be converted to Latin-1. The
+ * Latin-1 representation of the string is used with
+ * QApplication::translate(), if a translation for \a rMessage is
+ * requestd.
+ *
+ * \sa context(), translatedMessage(), translatedMessageWithArgs()
+ */
+ void setContext(const QString &rClassName);
+
+ /*!
+ * Sets the error message to \a rMessage
+ *
+ * \sa message()
+ */
+ void setMessage(const QString &rMessage);
+
+ /*!
+ * Sets the symbol for the error code to \a rSymbol.
+ *
+ * \sa symbol()
+ */
+ void setSymbol(const QString &rSymbol);
+
+ /*!
+ * Returns the last error set for the current thread using
+ * setLastError().
+ *
+ * \note: This function is thread-safe.
+ *
+ * \sa setLastError()
+ */
+ static LogError lastError();
+
+ /*!
+ * Sets the last error for the current thread to \a rLogError.
+ *
+ * \note: This function is thread-safe.
+ *
+ * \sa lastError()
+ */
+ static void setLastError(const LogError &rLogError);
+
+ /*!
+ * Appends \a rArg to the list of arguments and returns a reference to
+ * this error.
+ *
+ * \sa operator<<(), args(), clearArgs()
+ */
+ LogError &addArg(const QVariant &rArg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &addArg(int arg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &addArg(const QString &rArg);
+
+ /*!
+ * Appends \a rLogError to the list of causing errors and returns a
+ * reference to this error.
+ *
+ * \sa causingErrors(), clearCausingErrors()
+ */
+ LogError &addCausingError(const LogError &rLogError);
+
+ /*!
+ * Returns the list of arguments that have been added to this error.
+ *
+ * \sa addArg(), operator<<(), clearArgs()
+ */
+ QList<QVariant> args() const;
+
+ /*!
+ * Returns the list of causing errors that have been added to this error.
+ *
+ * \sa addArg(), operator<<(), clearArgs()
+ */
+ QList<LogError> causingErrors() const;
+
+ /*!
+ * Clears the list of arguments that have been added to this error.
+ *
+ * \sa addArg(), operator<<(), args()
+ */
+ void clearArgs();
+
+ /*!
+ * Clears the list of causing errors that have been added to this error.
+ *
+ * \sa addCausingError(), causingErrors()
+ */
+ void clearCausingErrors();
+
+ /*!
+ * Returns true, if the error code is 0 and the message is empty.
+ * Otherwise it returns false.
+ *
+ * \sa code(), message()
+ */
+ bool isEmpty() const;
+
+ /*!
+ * Returns the message with arguments. The arguments are incoorporated
+ * into the messag using QString::arg().
+ *
+ * \sa QString::arg(), translatedMessageWithArgs()
+ */
+ QString messageWithArgs() const;
+
+ /*!
+ * Returns the translated message with arguments. The arguments are
+ * incoorporated into the messag using QString::arg().
+ *
+ * \sa QString::arg(), messageWithArgs(), translatedMessage()
+ */
+ QString translatedMessageWithArgs() const;
+
+ /*!
+ * Appends \a rArg to the list of arguments and returns a reference to
+ * this error.
+ *
+ * \sa addArg()
+ */
+ LogError &operator<<(const QVariant &rArg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &operator<<(int arg);
+
+ /*!
+ * This is an overloaded member function, provided for convenience.
+ */
+ LogError &operator<<(const QString &rArg);
+
+ /*!
+ * Returns a string representation of the error.
+ *
+ * The string has the following format:
+ *
+ * <tt>
+ * message (context::symbol, code): causing_error, causing_error
+ * </tt>
+ *
+ * If members are empty they are omitted:
+ * - Omit context, if empty
+ * - Omit symbol, if empty
+ * - Omit double colon with context and symbol, if both are empty
+ * - Omit code, if 0
+ * - Omit bracket with context/symbol and code, if all are empty
+ * - Omit colon with causing errors, if no causing errors exist
+ */
+ QString toString() const;
+
+ private:
+ QString insertArgs(const QString &rMessage) const;
+ QString cleanMessage(const QString &rMessage);
+
+ private:
+ int mCode;
+ QString mContext;
+ QString mMessage;
+ QString mSymbol;
+ QList<QVariant> mArgs;
+ QList<LogError> mCausingErrors;
+
+#ifndef QT_NO_DATASTREAM
+ // Needs to be friend to stream objects
+ friend QDataStream &operator<<(QDataStream &rStream,
+ const LogError &rLogError);
+ friend QDataStream &operator>>(QDataStream &rStream,
+ LogError &rLogError);
+#endif // QT_NO_DATASTREAM
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+ /*!
+ * \relates LogError
+ *
+ * Writes the given error \a rLogError to the given stream \a rStream,
+ * and returns a reference to the stream.
+ */
+ QDataStream &operator<<(QDataStream &rStream,
+ const LogError &rLogError);
+
+ /*!
+ * \relates LogError
+ *
+ * Reads an error from the given stream \a rStream into the given
+ * error \a rLogError, and returns a reference to the stream.
+ */
+ QDataStream &operator>>(QDataStream &rStream,
+ LogError &rLogError);
+#endif // QT_NO_DATASTREAM
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LogError
+ *
+ * Writes all object member variables to the given debug stream \a debug and
+ * returns the stream.
+ *
+ * <tt>
+ * %LogError(code:7 context:"Log4Qt::FileAppender"
+ * message:"Unable to open file '%1' for appender '%2'"
+ * symbol:"APPENDER_OPENING_FILE_ERROR"
+ * args:(QVariant(QString, "G:\logs\client.log") , QVariant(QString, "Client FileAppender") )
+ * translatedMessage: "Unable to open file '%1' for appender '%2'" )
+ * </tt>
+ *
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const LogError &rLogError);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline int LogError::code() const
+ { return mCode; }
+
+ inline QString LogError::context() const
+ { return mContext; }
+
+ inline QString LogError::message() const
+ { return mMessage; }
+
+ inline QString LogError::symbol() const
+ { return mSymbol; }
+
+ inline void LogError::setCode(int code)
+ { mCode = code; }
+
+ inline void LogError::setContext(const QString &rContext)
+ { mContext = rContext; }
+
+ inline void LogError::setMessage(const QString &rMessage)
+ { mMessage = cleanMessage(rMessage); }
+
+ inline void LogError::setSymbol(const QString &rSymbol)
+ { mSymbol = rSymbol; }
+
+ inline LogError &LogError::addArg(const QVariant &rArg)
+ { mArgs << rArg; return *this; }
+
+ inline LogError &LogError::addArg(int arg)
+ { mArgs << QVariant(arg); return *this; }
+
+ inline LogError &LogError::addArg(const QString &rArg)
+ { mArgs << QVariant(rArg); return *this; }
+
+ inline LogError &LogError::addCausingError(const LogError &rLogError)
+ { mCausingErrors << rLogError; return *this; }
+
+ inline QList<QVariant> LogError::args() const
+ { return mArgs; }
+
+ inline void LogError::clearArgs()
+ { mArgs.clear(); }
+
+ inline void LogError::clearCausingErrors()
+ { mCausingErrors.clear(); }
+
+ inline QList<LogError> LogError::causingErrors() const
+ { return mCausingErrors; }
+
+ inline bool LogError::isEmpty() const
+ { return mCode || !mMessage.isEmpty(); }
+
+ inline QString LogError::messageWithArgs() const
+ { return insertArgs(message()); }
+
+ inline QString LogError::translatedMessageWithArgs() const
+ { return insertArgs(translatedMessage()); }
+
+ inline LogError &LogError::operator<<(const QVariant &rArg)
+ { return addArg(rArg); }
+
+ inline LogError &LogError::operator<<(int arg)
+ { return addArg(arg); }
+
+ inline LogError &LogError::operator<<(const QString &rArg)
+ { return addArg(rArg); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_METATYPE(Log4Qt::LogError)
+Q_DECLARE_TYPEINFO(Log4Qt::LogError, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_ERROR_H
diff --git a/ext/Log4Qt/src/helpers/logobject.cpp b/ext/Log4Qt/src/helpers/logobject.cpp
new file mode 100755
index 0000000..61331aa
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobject.cpp
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobject.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/logobject.h"
+
+#include <QtCore/QDebug>
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: LogObject
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject)
+ {
+ return rLogObject.debug(debug);
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/logobject.h b/ext/Log4Qt/src/helpers/logobject.h
new file mode 100755
index 0000000..ab8d964
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobject.h
@@ -0,0 +1,219 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobject.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Replaced usage of q_atomic_increment and q_atomic_decrement
+ * with QAtomicInt.
+ * Feb 2009, Martin Heinrich
+ * - Fixed a problem where the pParent parameter of the constructor
+ * was not passed on to the QObject constructor
+ *
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGOBJECT_H
+#define LOG4QT_LOGOBJECT_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QObject>
+
+#include "classlogger.h"
+#if QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)
+# include <QtCore/QAtomicInt>
+# ifndef Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
+# warning "QAtomicInt reference counting is not native. The class Log4Qt::LogObject is not thread-safe."
+# endif
+#endif
+
+
+namespace Log4Qt
+{
+
+ class Logger;
+
+ /*!
+ * \brief The class LogObject is the common base class for many classes
+ * in the package.
+ *
+ * The class inherits QObject to allow its subclass to be accessed using
+ * the Qt property system.
+ *
+ * LogObject objects provide a reference counter. A reference to the
+ * object is established by calling retain() and freed by calling
+ * release(). The object will delete itself when the reference counter
+ * is decremented to 0.
+ *
+ * A class specific logger can be accessed over logger().
+ *
+ * The class also implements generic streaming to QDebug. Streaming an
+ * object to QDebug will invoke debug() to create class specific output.
+ *
+ * \note All the functions declared in this class are thread-safe.
+ *
+ * \sa \ref Ownership "Object ownership",
+ * LOG4QT_DECLARE_QCLASS_LOGGER
+ */
+ class LOG4QT_EXPORT LogObject : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ /*!
+ * Creates a LogObject which is a child of \a pObject.
+ */
+ LogObject(QObject *pObject = 0);
+
+ /*!
+ * Destroys the LogObject.
+ */
+ virtual ~LogObject();
+
+ private:
+ LogObject(const LogObject &rOther); // Not implemented
+ LogObject &operator=(const LogObject &rOther); // Not implemented
+
+ public:
+ /*!
+ * Returns the value of the reference counter.
+ */
+ int referenceCount() const;
+
+ /*!
+ * Decrements the reference count of the object. If the reference count
+ * count reaches zero and the object does not have a parent the object
+ * is deleted.
+ */
+ void release();
+
+ /*!
+ * Increments the reference count of the object.
+ */
+ void retain();
+
+ protected:
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * Writes all object member variables to the given debug stream
+ * \a rDebug and returns the stream.
+ *
+ * The member function is used by
+ * QDebug operator<<(QDebug debug, const LogObject &rLogObject) to
+ * generate class specific output.
+ *
+ * \sa QDebug operator<<(QDebug debug, const LogObject &rLogObject)
+ */
+ virtual QDebug debug(QDebug &rDebug) const = 0;
+
+ // Needs to be friend to access internal data
+ friend QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject);
+ #endif // QT_NO_DEBUG_STREAM
+
+ /*!
+ * Returns a pointer to a Logger named after of the object.
+ *
+ * \sa Logger::logger(const char *pName)
+ */
+ Logger* logger() const;
+
+ private:
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ volatile int mReferenceCount;
+#else
+ mutable QAtomicInt mReferenceCount;
+#endif
+ mutable ClassLogger mLog4QtClassLogger;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+ #ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates LogObject
+ *
+ * Writes all object member variables to the given debug stream \a debug
+ * and returns the stream.
+ *
+ * To handle sub-classing the function uses the virtual member function
+ * debug(). This allows each class to generate its own output.
+ *
+ * \sa QDebug, debug()
+ */
+ QDebug operator<<(QDebug debug,
+ const LogObject &rLogObject);
+ #endif
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline LogObject::LogObject(QObject *pParent) :
+ QObject(pParent),
+ mReferenceCount()
+ {}
+
+ inline LogObject::~LogObject()
+ {}
+
+ inline int LogObject::referenceCount() const
+ {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ return mReferenceCount;
+#else
+ return mReferenceCount.loadAcquire();
+#endif
+ }
+
+ inline void LogObject::release()
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ { if ((q_atomic_decrement(&mReferenceCount) == 0) && !parent())
+ delete(this); }
+#else
+ { if (!mReferenceCount.deref())
+ delete(this); }
+#endif
+
+ inline void LogObject::retain()
+#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0)
+ { q_atomic_increment(&mReferenceCount); }
+#else
+ { mReferenceCount.ref(); }
+#endif
+
+ inline Logger *LogObject::logger() const
+ { return mLog4QtClassLogger.logger(this); }
+
+} // namespace Log4Qt
+
+
+// Q_DECLARE_TYPEINFO(Log4Qt::LogObject, Q_COMPLEX_TYPE); // Use default
+
+
+#endif // LOG4QT_LOGOBJECT_H
diff --git a/ext/Log4Qt/src/helpers/logobjectptr.cpp b/ext/Log4Qt/src/helpers/logobjectptr.cpp
new file mode 100755
index 0000000..07d97c0
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobjectptr.cpp
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobjectptr.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/logobjectptr.h"
+
+#include <QtCore/QDebug>
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Class implementation: LogObjectPtr
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/logobjectptr.h b/ext/Log4Qt/src/helpers/logobjectptr.h
new file mode 100755
index 0000000..cd74078
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/logobjectptr.h
@@ -0,0 +1,187 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logobjectptr.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_LOGOBJECTPTR_H
+#define LOG4QT_LOGOBJECTPTR_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include "logobject.h"
+
+namespace Log4Qt
+{
+ /*!
+ * \brief The class LogObjectPtr implements automatic reference counting
+ * for LogObject objects.
+ */
+ template <class T>
+ class LogObjectPtr
+ {
+ public:
+ /*!
+ * Constructs a 0 LogObject pointer.
+ */
+ LogObjectPtr();
+
+ /*!
+ * Constructs a LogObject pointer that points to the same object then
+ * \a rOther. The reference counter of the object is incremented by
+ * one.
+ */
+ LogObjectPtr(const LogObjectPtr<T> &rOther);
+
+ /*!
+ * Constructs a LogObject pointer that points to the object
+ * \a LogObject. The reference counter of the object is incremented by
+ * one.
+ */
+ LogObjectPtr(T *pLogObject);
+
+ /*!
+ * Assignment operator. Sets the LogObject pointer to point to the
+ * same object that \a rOther points to. The reference counter of the
+ * object the LogObjectPtr pointed to before the assignment is
+ * decremented by one. The reference counter of the object \a rOther
+ * is pointing to is incremented by one.
+ */
+ LogObjectPtr<T> &operator=(const LogObjectPtr<T> &rOther);
+
+ /*!
+ * Destructs the object. The reference counter of the object the
+ * LogObjectPtr points to is decremented by one.
+ */
+ ~LogObjectPtr();
+
+ /*!
+ * Assignment operator. Sets the LogObject pointer to point to the
+ * object \a pLogObject. The reference counter of the object the
+ * LogObjectPtr pointed to before the assignment is decremented by
+ * one. The reference counter of the object \a pLogObject is pointing
+ * to is incremented by one.
+ */
+ LogObjectPtr<T> &operator=(T *pLogObject);
+
+ /*!
+ * Arrow operator. Returns the LogObject the object points to.
+ */
+ T *operator->() const;
+
+ /*!
+ * Dereference operator. Returns a pointer to the LogObject the
+ * object points to.
+ */
+ T &operator*() const;
+
+ /*!
+ * Cast operator. Cast the object to the LogObject the object points
+ * to.
+ */
+ operator T*() const;
+
+ private:
+ void retain() const;
+ void release() const;
+
+ private:
+ T *mpLogObject;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ template <class T>
+ inline LogObjectPtr<T>::LogObjectPtr() :
+ mpLogObject(0)
+ {}
+
+ template <class T>
+ inline LogObjectPtr<T>::LogObjectPtr(const LogObjectPtr<T> &rOther) :
+ mpLogObject(rOther.mpLogObject)
+ { retain(); }
+
+ template <class T>
+ inline LogObjectPtr<T>::LogObjectPtr(T *pLogObject) :
+ mpLogObject(pLogObject)
+ { retain(); }
+
+ template <class T>
+ inline LogObjectPtr<T> &LogObjectPtr<T>::operator=(const LogObjectPtr<T> &rOther)
+ { rOther.retain();
+ release();
+ mpLogObject = rOther.mpLogObject;
+ return *this; }
+
+ template <class T>
+ inline LogObjectPtr<T>::~LogObjectPtr()
+ { release(); }
+
+ template <class T>
+ inline LogObjectPtr<T> &LogObjectPtr<T>::operator=(T *pLogObject)
+ { if (pLogObject)
+ reinterpret_cast<LogObject *>(pLogObject)->retain();
+ release();
+ mpLogObject = pLogObject;
+ return *this; }
+
+ template <class T>
+ inline T *LogObjectPtr<T>::operator->() const
+ { return mpLogObject; }
+
+ template <class T>
+ inline T &LogObjectPtr<T>::operator*() const
+ { return *mpLogObject; }
+
+ template <class T>
+ inline LogObjectPtr<T>::operator T*() const
+ { return mpLogObject; }
+
+ template <class T>
+ inline void LogObjectPtr<T>::retain() const
+ { if (mpLogObject)
+ reinterpret_cast<LogObject *>(mpLogObject)->retain(); }
+
+ template <class T>
+ inline void LogObjectPtr<T>::release() const
+ {
+ if (mpLogObject)
+ reinterpret_cast<LogObject *>(mpLogObject)->release();
+ }
+
+} // namespace Log4Qt
+
+
+//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<T>, Q_MOVABLE_TYPE); // Declare within T
+
+
+#endif // LOG4QT_LOGOBJECTPTR_H
diff --git a/ext/Log4Qt/src/helpers/optionconverter.cpp b/ext/Log4Qt/src/helpers/optionconverter.cpp
new file mode 100755
index 0000000..e148a2d
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/optionconverter.cpp
@@ -0,0 +1,301 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: optionconverter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed a problem were OptionConverter::toBoolean would not
+ * return the default value, if the conversion fails.
+ *
+ *
+ * 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 "helpers/optionconverter.h"
+
+#include <QtCore/QDebug>
+#include "helpers/logerror.h"
+#include "helpers/properties.h"
+#include "logger.h"
+#include "consoleappender.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::OptionConverter)
+
+
+
+ /**************************************************************************
+ * Class implementation: OptionConverter
+ **************************************************************************/
+
+
+ QString OptionConverter::findAndSubst(const Properties &rProperties,
+ const QString &rKey)
+ {
+ QString value = rProperties.property(rKey);
+ if (value.isNull())
+ return value;
+
+ const QString begin_subst = QLatin1String("${");
+ const QString end_subst = QLatin1String("}");
+ const int begin_length = begin_subst.length();
+ const int end_length = end_subst.length();
+
+ // Don't return a null string, the null string indicates that the
+ // property key does not exist.
+ QString result = QLatin1String("");
+
+ int i = 0;
+ int begin;
+ int end;
+ while (i < value.length())
+ {
+ begin = value.indexOf(begin_subst, i);
+ if (begin == -1)
+ {
+ result += value.mid(i);
+ i = value.length();
+ }
+ else
+ {
+ result += value.mid(i, begin - i);
+ end = value.indexOf(end_subst, i + begin_length);
+ if (end == -1)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing closing bracket for opening bracket at %1. Invalid subsitution in value %2."),
+ CONFIGURATOR_INVALID_SUBSTITUTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << begin << value;
+ logger()->error(e);
+ return result;
+ }
+ else
+ {
+ result += findAndSubst(rProperties, value.mid(begin + begin_length, end - begin - end_length - 1));
+ i = end + end_length;
+ }
+ }
+ }
+ return result;
+ }
+
+
+ QString OptionConverter::classNameJavaToCpp(const QString &rClassName)
+ {
+ const QLatin1String java_class_delimiter(".");
+ const QLatin1String cpp_class_delimiter("::");
+
+ QString result = rClassName;
+ return result.replace(java_class_delimiter, cpp_class_delimiter);
+ }
+
+
+ bool OptionConverter::toBoolean(const QString &rOption,
+ bool *p_ok)
+ {
+ const QLatin1String str_true("true");
+ const QLatin1String str_enabled("enabled");
+ const QLatin1String str_one("1");
+ const QLatin1String str_false("false");
+ const QLatin1String str_disabled("disabled");
+ const QLatin1String str_zero("0");
+
+ if (p_ok)
+ *p_ok = true;
+ QString s = rOption.trimmed().toLower();
+ if (s == str_true || s == str_enabled || s == str_one)
+ return true;
+ if (s == str_false || s == str_disabled || s == str_zero)
+ return false;
+
+ if (p_ok)
+ *p_ok = false;
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a boolean"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return false;
+ }
+
+
+ bool OptionConverter::toBoolean(const QString &rOption,
+ bool default_value)
+ {
+ bool ok;
+ bool result = toBoolean(rOption, &ok);
+ if (ok)
+ return result;
+ else
+ return default_value;
+ }
+
+ qint64 OptionConverter::toFileSize(const QString &rOption,
+ bool *p_ok)
+ {
+ // - Search for unit
+ // - Convert characters befor unit to int
+ // - Error, if
+ // - the conversion failed
+ // - the value < 0
+ // - there is text after the unit characters
+
+ if (p_ok)
+ *p_ok = false;
+ QString s = rOption.trimmed().toLower();
+ qint64 f = 1;
+ int i;
+ i = s.indexOf(QLatin1String("kb"));
+ if (i >= 0)
+ f = 1024;
+ else
+ {
+ i = s.indexOf(QLatin1String("mb"));
+ if (i >= 0)
+ f = 1024 * 1024;
+ else
+ {
+ i = s.indexOf(QLatin1String("gb"));
+ if (i >= 0)
+ f = 1024 * 1024 * 1024;
+ }
+ }
+ if (i < 0)
+ i = s.length();
+ bool ok;
+ qint64 value = s.left(i).toLongLong(&ok);
+ if (!ok || value < 0 || s.length() > i + 2)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a file size"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return 0;
+ }
+ if (p_ok)
+ *p_ok = true;
+ return value * f;
+ }
+
+
+ int OptionConverter::toInt(const QString &rOption,
+ bool *p_ok)
+ {
+ int value = rOption.trimmed().toInt(p_ok);
+ if (*p_ok)
+ return value;
+
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for an integer"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return 0;
+ }
+
+
+ Level OptionConverter::toLevel(const QString &rOption,
+ bool *p_ok)
+ {
+ bool ok;
+ Level level = Level::fromString(rOption.toUpper().trimmed(), &ok);
+ if (p_ok)
+ *p_ok = ok;
+ if (ok)
+ return level;
+
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a level"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return level;
+ }
+
+
+ Level OptionConverter::toLevel(const QString &rOption,
+ const Level &rDefaultValue)
+ {
+ bool ok;
+ Level result = toLevel(rOption, &ok);
+ if (ok)
+ return result;
+ else
+ return rDefaultValue;
+ }
+
+
+ int OptionConverter::toTarget(const QString &rOption,
+ bool *p_ok)
+ {
+ const QLatin1String java_stdout("system.out");
+ const QLatin1String cpp_stdout("stdout_target");
+ const QLatin1String java_stderr("system.err");
+ const QLatin1String cpp_stderr("stderr_target");
+
+ if (p_ok)
+ *p_ok = true;
+ QString s = rOption.trimmed().toLower();
+ if (s == java_stdout || s == cpp_stdout)
+ return ConsoleAppender::STDOUT_TARGET;
+ if (s == java_stderr || s == cpp_stderr)
+ return ConsoleAppender::STDERR_TARGET;
+
+ if (p_ok)
+ *p_ok = false;
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Invalid option string '%1' for a target"),
+ CONFIGURATOR_INVALID_OPTION_ERROR,
+ "Log4Qt::OptionConverter");
+ e << rOption;
+ logger()->error(e);
+ return ConsoleAppender::STDOUT_TARGET;
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/optionconverter.h b/ext/Log4Qt/src/helpers/optionconverter.h
new file mode 100755
index 0000000..ebdd567
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/optionconverter.h
@@ -0,0 +1,141 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: optionconverter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_OPTIONCONVERTER_H
+#define LOG4QT_OPTIONCONVERTER_H
+#include "../log4qtshared.h"
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QString>
+#include "level.h"
+
+namespace Log4Qt
+{
+ class Properties;
+
+ /*!
+ * \brief The class OptionConverter provides functions to convert strings
+ * to property values.
+ */
+ class LOG4QT_EXPORT OptionConverter
+ {
+ private:
+ OptionConverter();
+ OptionConverter(const OptionConverter &rOther); // Not implemented
+ // virtual ~OptionConverter(); // Use compiler default
+ OptionConverter &operator=(const OptionConverter &rOther); // Not implemented
+
+ public:
+ static QString findAndSubst(const Properties &rProperties,
+ const QString &rKey);
+
+ /*!
+ * Returns the JAVA class name \a rClassName as C++ class name by
+ * replacing all . characters with ::.
+ */
+ static QString classNameJavaToCpp(const QString &rClassName);
+
+ /*!
+ * Converts the option \a rOption to a boolean value. Valid strings
+ * for true are "true", "enabled" and "1". Valid strings
+ * for false are "false", "disabled" and "0". If the conversion is
+ * successful, the target is returned and \a p_ok is set to true.
+ * Otherwise an error is written to the log, \a p_ok is set to false
+ * and false is returned.
+ */
+ static bool toBoolean(const QString &rOption,
+ bool *p_ok = 0);
+
+ static bool toBoolean(const QString &rOption,
+ bool default_value);
+
+ /*!
+ * Converts the option string \a rOption to a file size. The string can
+ * be a positive integer followed by an optional unit suffix "KB", "MB"
+ * or "GB". If a unit suffix is specified the the integer is
+ * interpreted as kilobytes, megabytes or gigabytes. If the conversion
+ * is successful, the size is returned and \a p_ok is set to true.
+ * Otherwise an error is written to the log, \a p_ok is set to false
+ * and 0 is returned.
+ */
+ static qint64 toFileSize(const QString &rOption,
+ bool *p_ok = 0);
+
+ /*!
+ * Converts the option \a rOption to a integer value using
+ * QString::toInt(). If the conversion is successful, the integer is
+ * returned and \a p_ok is set to true. Otherwise an error is written
+ * to the log, \a p_ok is set to false and 0 is returned.
+ */
+ static int toInt(const QString &rOption,
+ bool *p_ok = 0);
+
+ /*!
+ * Converts the option \a rOption to a level value using
+ * Level::fromString(). If the conversion is successful, the level
+ * is returned and \a p_ok is set to true. Otherwise an error is
+ * written to the log, \a p_ok is set to false and a level with
+ * the value Level::NULL_INT is returned.
+ *
+ * \sa Level::fromString()
+ */
+ static Level toLevel(const QString &rOption,
+ bool *p_ok = 0);
+
+ static Level toLevel(const QString &rOption,
+ const Level &rDefaultValue);
+
+ /*!
+ * Converts the option \a rOption to a ConsoleAppender::Target value.
+ * Valid strings for \a rOption are "System.out", "STDOUT_TARGET",
+ * "System.err" and "STDERR_TARGET". If the conversion is successful,
+ * the target is returned and \a p_ok is set to true. Otherwise an
+ * error is written to the log, \a p_ok is set to false and
+ * ConsoleAppender::STDOUT_TARGET is returned.
+ */
+ static int toTarget(const QString &rOption,
+ bool *p_ok = 0);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::OptionConverter, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_OPTIONCONVERTER_H
diff --git a/ext/Log4Qt/src/helpers/patternformatter.cpp b/ext/Log4Qt/src/helpers/patternformatter.cpp
new file mode 100644
index 0000000..cf23198
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/patternformatter.cpp
@@ -0,0 +1,902 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: patternformatter.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in LiteralPatternConverter::convert.
+ *
+ *
+ * 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 "helpers/patternformatter.h"
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <limits.h>
+#include "helpers/datetime.h"
+#include "helpers/logerror.h"
+#include "layout.h"
+#include "logger.h"
+#include "loggingevent.h"
+
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+ /*!
+ * \brief The class FormattingInfo stores the formatting modifier for a
+ * pattern converter.
+ *
+ * \sa PatternConverter
+ */
+ class FormattingInfo
+ {
+ public:
+ FormattingInfo()
+ { clear(); }
+ // FormattingInfo(const FormattingInfo &rOther); // Use compiler default
+ // virtual ~FormattingInfo(); // Use compiler default
+ // FormattingInfo &operator=(const FormattingInfo &rOther); // Use compiler default
+
+ void clear();
+ static QString intToString(int i);
+
+ public:
+ int mMinLength;
+ int mMaxLength;
+ bool mLeftAligned;
+ };
+
+
+ /*!
+ * \brief The class PatternConverter is the abstract base class for all
+ * pattern converters.
+ *
+ * PatternConverter handles the minimum and maximum modifier for a
+ * conversion character. The actual conversion is by calling the
+ * convert() member function of the derived class.
+ *
+ * \sa PatternLayout::format()
+ */
+ class PatternConverter
+ {
+ public:
+ PatternConverter(const FormattingInfo &rFormattingInfo = FormattingInfo()) :
+ mFormattingInfo(rFormattingInfo)
+ {};
+ virtual ~PatternConverter()
+ {};
+ private:
+ PatternConverter(const PatternConverter &rOther); // Not implemented
+ PatternConverter &operator=(const PatternConverter &rOther); // Not implemented
+
+ public:
+ void format(QString &rFormat, const LoggingEvent &rLoggingEvent) const;
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const = 0;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const = 0;
+ friend QDebug operator<<(QDebug, const PatternConverter &rPatternConverter);
+ #endif
+
+ protected:
+ FormattingInfo mFormattingInfo;
+ };
+
+
+ /*!
+ * \brief The class BasicPatternConverter converts several members of a
+ * LoggingEvent to a string.
+ *
+ * BasicPatternConverter is used by PatternLayout to convert members that
+ * do not reuquire additional formatting to a string as part of formatting
+ * the LoggingEvent. It handles the following conversion characters:
+ * 'm', 'p', 't', 'x'
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class BasicPatternConverter : public PatternConverter
+ {
+ public:
+ enum Type {
+ MESSAGE_CONVERTER,
+ NDC_CONVERTER,
+ LEVEL_CONVERTER,
+ THREAD_CONVERTER
+ };
+
+ public:
+ BasicPatternConverter(const FormattingInfo &rFormattingInfo,
+ Type type) :
+ PatternConverter(rFormattingInfo),
+ mType(type)
+ {};
+ // virtual ~BasicPatternConverter(); // Use compiler default
+ private:
+ BasicPatternConverter(const BasicPatternConverter &rOther); // Not implemented
+ BasicPatternConverter &operator=(const BasicPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ Type mType;
+ };
+
+
+ /*!
+ * \brief The class DatePatternConverter converts the time stamp of a
+ * LoggingEvent to a string.
+ *
+ * DatePatternConverter is used by PatternLayout to convert the time stamp
+ * of a LoggingEvent to a string as part of formatting the LoggingEvent.
+ * It handles the 'd' and 'r' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class DatePatternConverter : public PatternConverter
+ {
+ public:
+ DatePatternConverter(const FormattingInfo &rFormattingInfo,
+ const QString &rFormat) :
+ PatternConverter(rFormattingInfo),
+ mFormat(rFormat)
+ {};
+ // virtual ~DatePatternConverter(); // Use compiler default
+ private:
+ DatePatternConverter(const DatePatternConverter &rOther); // Not implemented
+ DatePatternConverter &operator=(const DatePatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ QString mFormat;
+ };
+
+
+ /*!
+ * \brief The class LiteralPatternConverter provides string literals.
+ *
+ * LiteralPatternConverter is used by PatternLayout to embed string
+ * literals as part of formatting the LoggingEvent. It handles string
+ * literals and the 'n' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class LiteralPatternConverter : public PatternConverter
+ {
+ public:
+ LiteralPatternConverter(const QString &rLiteral) :
+ PatternConverter(),
+ mLiteral(rLiteral)
+ {};
+ // virtual ~LiteralPatternConverter(); // Use compiler default
+ private:
+ LiteralPatternConverter(const LiteralPatternConverter &rOther); // Not implemented
+ LiteralPatternConverter &operator=(const LiteralPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ QString mLiteral;
+ };
+
+
+ /*!
+ * \brief The class LoggerPatternConverter converts the Logger name of a
+ * LoggingEvent to a string.
+ *
+ * LoggerPatternConverter is used by PatternLayout to convert the Logger
+ * name of a LoggingEvent to a string as part of formatting the
+ * LoggingEvent. It handles the 'c' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class LoggerPatternConverter : public PatternConverter
+ {
+ public:
+ LoggerPatternConverter(const FormattingInfo &rFormattingInfo,
+ int precision) :
+ PatternConverter(rFormattingInfo),
+ mPrecision(precision)
+ {};
+ // virtual ~LoggerPatternConverter(); // Use compiler default
+ private:
+ LoggerPatternConverter(const LoggerPatternConverter &rOther); // Not implemented
+ LoggerPatternConverter &operator=(const LoggerPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ int mPrecision;
+ };
+
+
+
+ /*!
+ * \brief The class MDCPatternConverter converts the MDC data of a
+ * LoggingEvent to a string.
+ *
+ * MDCPatternConverter is used by PatternLayout to convert the MDC data of
+ * a LoggingEvent to a string as part of formatting the LoggingEvent. It
+ * handles the 'X' conversion character.
+ *
+ * \sa PatternLayout::format()
+ * \sa PatternConverter::format()
+ */
+ class MDCPatternConverter : public PatternConverter
+ {
+ public:
+ MDCPatternConverter(const FormattingInfo &rFormattingInfo,
+ const QString &rKey) :
+ PatternConverter(rFormattingInfo),
+ mKey(rKey)
+ {};
+ // virtual ~MDCPatternConverter(); // Use compiler default
+ private:
+ MDCPatternConverter(const MDCPatternConverter &rOther); // Not implemented
+ MDCPatternConverter &operator=(const MDCPatternConverter &rOther); // Not implemented
+
+ protected:
+ virtual QString convert(const LoggingEvent &rLoggingEvent) const;
+ #ifndef QT_NO_DEBUG_STREAM
+ virtual QDebug debug(QDebug &rDebug) const;
+ #endif
+
+ private:
+ QString mKey;
+ };
+
+
+ #ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug, const FormattingInfo &rFormattingInfo);
+ #endif
+
+
+ #ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug, const PatternConverter &rPatternConverter);
+ #endif
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PatternFormatter)
+
+
+
+ /**************************************************************************
+ * Class implementation: PatternFormatter
+ **************************************************************************/
+
+
+ PatternFormatter::PatternFormatter(const QString &rPattern) :
+ mIgnoreCharacters(QLatin1String("CFlLM")),
+ mConversionCharacters(QLatin1String("cdmprtxX")),
+ mOptionCharacters(QLatin1String("cd")),
+ mPattern(rPattern),
+ mPatternConverters()
+ {
+ parse();
+ }
+
+
+ PatternFormatter::~PatternFormatter()
+ {
+ PatternConverter *p_converter;
+ Q_FOREACH(p_converter, mPatternConverters)
+ delete p_converter;
+ }
+
+
+ QString PatternFormatter::format(const LoggingEvent &rLoggingEvent) const
+ {
+ QString result;
+ PatternConverter *p_converter;
+ Q_FOREACH(p_converter, mPatternConverters)
+ p_converter->format(result, rLoggingEvent);
+ return result;
+ }
+
+
+ bool PatternFormatter::addDigit(const QChar &rDigit,
+ int &rValue)
+ {
+ if (!rDigit.isDigit())
+ return false;
+
+ int digit_value = rDigit.digitValue();
+ if (rValue > (INT_MAX - digit_value) / 10)
+ rValue = INT_MAX;
+ else
+ rValue = rValue * 10 + digit_value;
+ return true;
+ }
+
+
+ void PatternFormatter::createConverter(const QChar &rChar,
+ const FormattingInfo &rFormattingInfo,
+ const QString &rOption)
+ {
+ Q_ASSERT_X(mConversionCharacters.indexOf(rChar) >= 0, "PatternFormatter::createConverter", "Unknown conversion character" );
+
+ LogError e("Creating Converter for character '%1' min %2, max %3, left %4 and option '%5'");
+ e << QString(rChar)
+ << FormattingInfo::intToString(rFormattingInfo.mMinLength)
+ << FormattingInfo::intToString(rFormattingInfo.mMaxLength)
+ << rFormattingInfo.mLeftAligned
+ << rOption;
+ logger()->trace(e);
+
+ switch (rChar.toLatin1())
+ {
+ case 'c':
+ mPatternConverters << new LoggerPatternConverter(rFormattingInfo,
+ parseIntegerOption(rOption));
+ break;
+ case 'd':
+ {
+ QString option = rOption;
+ if (rOption.isEmpty()) {
+ option = QLatin1String("ISO8601");
+ } else if (rOption == "locale:long") {
+ option = QLocale().dateTimeFormat(QLocale::LongFormat);
+ } else if (rOption == "locale:short") {
+ option = QLocale().dateTimeFormat(QLocale::ShortFormat);
+ } else if (rOption == "locale:narrow") {
+ option = QLocale().dateTimeFormat(QLocale::NarrowFormat);
+ } else if (rOption == "locale") {
+ option = QLocale().dateTimeFormat(QLocale::ShortFormat);
+ }
+ mPatternConverters << new DatePatternConverter(rFormattingInfo,
+ option);
+ break;
+ }
+ case 'm':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::MESSAGE_CONVERTER);
+ break;
+ case 'p':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::LEVEL_CONVERTER);
+ break;
+ case 'r':
+ mPatternConverters << new DatePatternConverter(rFormattingInfo,
+ QLatin1String("RELATIVE"));
+ break;
+ case 't':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::THREAD_CONVERTER);
+ break;
+ case 'x':
+ mPatternConverters << new BasicPatternConverter(rFormattingInfo,
+ BasicPatternConverter::NDC_CONVERTER);
+ break;
+ case 'X':
+ mPatternConverters << new MDCPatternConverter(rFormattingInfo,
+ rOption);
+ break;
+ default:
+ Q_ASSERT_X(false, "PatternFormatter::createConverter", "Unknown pattern character");
+ }
+ }
+
+
+ void PatternFormatter::createLiteralConverter(const QString &rLiteral)
+ {
+ logger()->trace("Creating literal LiteralConverter with Literal '%1'",
+ rLiteral);
+ mPatternConverters << new LiteralPatternConverter(rLiteral);
+ }
+
+
+ void PatternFormatter::parse()
+ {
+ enum State {
+ LITERAL_STATE,
+ ESCAPE_STATE,
+ MIN_STATE,
+ DOT_STATE,
+ MAX_STATE,
+ CHARACTER_STATE,
+ POSSIBLEOPTION_STATE,
+ OPTION_STATE
+ };
+
+ int i = 0;
+ QChar c;
+ char ch;
+ State state = LITERAL_STATE;
+ FormattingInfo formatting_info;
+ QString literal;
+ int converter_start = 0;
+ int option_start = 0;
+ while (i < mPattern.length())
+ {
+ // i points to the current character
+ // c contains the current character
+ // ch contains the Latin1 equivalent of the current character
+ // i is incremented at the end of the loop to consume the character
+ // continue is used to change state without consuming the character
+
+ c = mPattern.at(i);
+ ch = c.toLatin1();
+ switch (state)
+ {
+ case LITERAL_STATE:
+ if (ch == '%')
+ {
+ formatting_info.clear();
+ converter_start = i;
+ state = ESCAPE_STATE;
+ } else
+ literal += c;
+ break;
+ case ESCAPE_STATE:
+ if (ch == '%')
+ {
+ literal += c;
+ state = LITERAL_STATE;
+ }
+ else if (ch == 'n')
+ {
+ literal += Layout::endOfLine();
+ state = LITERAL_STATE;
+ }
+ else
+ {
+ if (!literal.isEmpty())
+ {
+ createLiteralConverter(literal);
+ literal.clear();
+ }
+ if (ch == '-')
+ formatting_info.mLeftAligned = true;
+ else if (c.isDigit())
+ {
+ formatting_info.mMinLength = c.digitValue();
+ state = MIN_STATE;
+ }
+ else if (ch == '.')
+ state = DOT_STATE;
+ else
+ {
+ state = CHARACTER_STATE;
+ continue;
+ }
+ }
+ break;
+ case MIN_STATE:
+ if (!addDigit(c, formatting_info.mMinLength))
+ {
+ if (ch == '.')
+ state = DOT_STATE;
+ else
+ {
+ state = CHARACTER_STATE;
+ continue;
+ }
+ }
+ break;
+ case DOT_STATE:
+ if (c.isDigit())
+ {
+ formatting_info.mMaxLength = c.digitValue();
+ state = MAX_STATE;
+ }
+ else
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Found character '%1' where digit was expected."),
+ LAYOUT_EXPECTED_DIGIT_ERROR,
+ "Log4Qt::PatternFormatter");
+ e << QString(c);
+ logger()->error(e);
+ }
+ break;
+ case MAX_STATE:
+ if (!addDigit(c, formatting_info.mMaxLength))
+ {
+ state = CHARACTER_STATE;
+ continue;
+ }
+ break;
+ case CHARACTER_STATE:
+ if (mIgnoreCharacters.indexOf(c) >= 0)
+ state = LITERAL_STATE;
+ else if (mOptionCharacters.indexOf(c) >= 0)
+ state = POSSIBLEOPTION_STATE;
+ else if (mConversionCharacters.indexOf(c) >= 0)
+ {
+ createConverter(c, formatting_info);
+ state = LITERAL_STATE;
+ }
+ else
+ {
+ logger()->warn("Invalid conversion character '%1' at %2 in pattern '%3'",
+ c, i, mPattern);
+ createLiteralConverter(mPattern.mid(converter_start, i - converter_start + 1));
+ state = LITERAL_STATE;
+ }
+ break;
+ case POSSIBLEOPTION_STATE:
+ if (ch == '{')
+ {
+ option_start = i;
+ state = OPTION_STATE;
+ }
+ else
+ {
+ createConverter(mPattern.at(i - 1),
+ formatting_info);
+ state = LITERAL_STATE;
+ continue;
+ }
+ break;
+ case OPTION_STATE:
+ if (ch == '}')
+ {
+ createConverter(mPattern.at(option_start - 1),
+ formatting_info,
+ mPattern.mid(option_start + 1, i - option_start - 1));
+ state = LITERAL_STATE;
+ }
+ break;
+ default:
+ Q_ASSERT_X(false, "PatternFormatter::parse()", "Unknown parsing state constant");
+ state = LITERAL_STATE;
+ }
+ i++;
+ }
+
+ if (state != LITERAL_STATE)
+ {
+ logger()->warn("Unexptected end of pattern '%1'", mPattern);
+ if (state == ESCAPE_STATE)
+ literal += c;
+ else
+ literal += mPattern.mid(converter_start);
+ }
+
+ if (!literal.isEmpty())
+ createLiteralConverter(literal);
+ }
+
+
+ int PatternFormatter::parseIntegerOption(const QString &rOption)
+ {
+ if (rOption.isEmpty())
+ return 0;
+
+ bool ok;
+ int result = rOption.toInt(&ok);
+ if (!ok)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option '%1' cannot be converted into an integer"),
+ LAYOUT_OPTION_IS_NOT_INTEGER_ERROR,
+ "Log4Qt::PatterFormatter");
+ e << rOption;
+ logger()->error(e);
+ }
+ if (result < 0)
+ {
+ LogError e = LOG4QT_ERROR(QT_TR_NOOP("Option %1 isn't a positive integer"),
+ LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR,
+ "Log4Qt::PatterFormatter");
+ e << result;
+ logger()->error(e);
+ result = 0;
+ }
+ return result;
+ }
+
+
+ /**************************************************************************
+ * Class implementation: FormattingInfo
+ **************************************************************************/
+
+
+ void FormattingInfo::clear()
+ {
+ mMinLength = 0;
+ mMaxLength = INT_MAX;
+ mLeftAligned = false;
+ }
+
+
+ QString FormattingInfo::intToString(int i)
+ {
+ if (i == INT_MAX)
+ return QLatin1String("INT_MAX");
+ else
+ return QString::number(i);
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: PatternConverter
+ **************************************************************************/
+
+
+ void PatternConverter::format(QString &rFormat, const LoggingEvent &rLoggingEvent) const
+ {
+ const QLatin1Char space(' ');
+ QString s = convert(rLoggingEvent);
+
+ if (s.length() > mFormattingInfo.mMaxLength)
+ rFormat += s.left(mFormattingInfo.mMaxLength);
+ else if (mFormattingInfo.mLeftAligned)
+ rFormat += s.leftJustified(mFormattingInfo.mMinLength, space, false);
+ else
+ rFormat += s.rightJustified(mFormattingInfo.mMinLength, space, false);
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: BasicPatternConverter
+ **************************************************************************/
+
+
+ QString BasicPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ switch (mType)
+ {
+ case MESSAGE_CONVERTER:
+ return rLoggingEvent.message();
+ break;
+ case NDC_CONVERTER:
+ return rLoggingEvent.ndc();
+ break;
+ case LEVEL_CONVERTER:
+ return rLoggingEvent.level().toString();
+ break;
+ case THREAD_CONVERTER:
+ return rLoggingEvent.threadName();
+ break;
+ default:
+ Q_ASSERT_X(false, "BasicPatternConverter::convert()", "Unkown type constant");
+ return QString();
+ }
+ }
+
+
+ QDebug BasicPatternConverter::debug(QDebug &rDebug) const
+ {
+ QString type;
+ switch (mType)
+ {
+ case MESSAGE_CONVERTER:
+ type = QLatin1String("MESSAGE_CONVERTER");
+ break;
+ case NDC_CONVERTER:
+ type = QLatin1String("NDC_CONVERTER");
+ break;
+ case LEVEL_CONVERTER:
+ type = QLatin1String("LEVEL_CONVERTER");
+ break;
+ case THREAD_CONVERTER:
+ type = QLatin1String("THREAD_CONVERTER");
+ break;
+ default:
+ Q_ASSERT_X(false, "BasicPatternConverter::debug()", "Unkown type constant");
+ }
+ rDebug.nospace() << "BasicPatternConverter("
+ << mFormattingInfo
+ << "type:" << type
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: DatePatternConverter
+ **************************************************************************/
+
+
+ QString DatePatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ return DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()).toString(mFormat);
+ }
+
+
+ QDebug DatePatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "DatePatternConverter("
+ << mFormattingInfo
+ << "format:" << mFormat
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: LiteralPatternConverter
+ **************************************************************************/
+
+
+ QString LiteralPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ Q_UNUSED(rLoggingEvent);
+ return mLiteral;
+ }
+
+
+ QDebug LiteralPatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "LiteralPatternConverter("
+ << mFormattingInfo
+ << "literal:" << mLiteral
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Class implementation: LoggerPatternConverter
+ **************************************************************************/
+
+
+ QString LoggerPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ if (!rLoggingEvent.logger())
+ return QString();
+ QString name = rLoggingEvent.logger()->name();
+ if (mPrecision <= 0 || (name.isEmpty()))
+ return name;
+
+ const QString separator(QLatin1String("::"));
+
+ int i = mPrecision;
+ int begin = name.length();
+ while ((i > 0) && (begin >= 0))
+ {
+ begin = name.lastIndexOf(separator, begin - name.length() - 1);
+ i--;
+ }
+ if (begin < 0)
+ begin = 0;
+ else
+ begin += 2;
+ return name.mid(begin);
+ }
+
+
+ QDebug LoggerPatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "LoggerPatternConverter("
+ << mFormattingInfo
+ << "precision:" << mPrecision
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /******************************************************************************
+ * Class implementation: MDCPatternConverter
+ ******************************************************************************/
+
+
+ QString MDCPatternConverter::convert(const LoggingEvent &rLoggingEvent) const
+ {
+ return rLoggingEvent.mdc().value(mKey);
+ }
+
+
+ QDebug MDCPatternConverter::debug(QDebug &rDebug) const
+ {
+ rDebug.nospace() << "MDCPatternConverter("
+ << mFormattingInfo
+ << "key:" << mKey
+ << ")";
+ return rDebug.space();
+ }
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+ #ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const PatternFormatter &rPatternFormatter)
+ {
+ debug.nospace() << "PatternFormatter("
+ << "pattern:" << rPatternFormatter.mPattern << " "
+ << "converters:(";
+ int i;
+ for (i = 0; i < rPatternFormatter.mPatternConverters.size(); i++)
+ {
+ if (i > 0)
+ debug.nospace() << ", ";
+ debug.nospace() << *rPatternFormatter.mPatternConverters.at(i);
+ }
+ debug.nospace() << ") )";
+ return debug.space();
+ }
+ #endif
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const FormattingInfo &rFormattingInfo)
+ {
+ debug.nospace() << "FormattingInfo("
+ << "min:" << FormattingInfo::intToString(rFormattingInfo.mMinLength) << " "
+ << "max:" << FormattingInfo::intToString(rFormattingInfo.mMaxLength) << " "
+ << "left:" << rFormattingInfo.mLeftAligned
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const PatternConverter &rPatternConverter)
+ {
+ return rPatternConverter.debug(debug);
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/patternformatter.h b/ext/Log4Qt/src/helpers/patternformatter.h
new file mode 100755
index 0000000..4bbe5fc
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/patternformatter.h
@@ -0,0 +1,195 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: patternformatter.h
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_PATTERNFORMATTER_H
+#define LOG4QT_PATTERNFORMATTER_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+
+namespace Log4Qt
+{
+
+ class FormattingInfo;
+ class PatternConverter;
+ class LoggingEvent;
+
+ /*!
+ * \brief The class PatternFormatter formats a logging event based on a
+ * pattern string.
+ *
+ * The class PatternFormatter formats a LoggingEvent base on a pattern
+ * string. It is used by the patternLayout and TTCCLayout class to
+ * implement the formatting.
+ *
+ * On object construction the provided patterns tring is parsed. Based on
+ * the information found a chain of PatternConverter is created. Each
+ * PatternConverter handles a certain member of a LoggingEvent.
+ *
+ * \sa PatternLayout::format()
+ * \sa TTCCLayout::format()
+ */
+ class LOG4QT_EXPORT PatternFormatter
+ {
+ public:
+ /*!
+ * Creates a PatternFormatter using a the specified \a rPattern.
+ */
+ PatternFormatter(const QString &rPattern);
+
+ /*!
+ * Destroys the PatternFormatter and all PatternConverter.
+ */
+ virtual ~PatternFormatter();
+
+ private:
+ PatternFormatter(const PatternFormatter &rOther); // Not implemented
+ PatternFormatter &operator=(const PatternFormatter &rOther); // Not implemented
+
+ public:
+ /*!
+ * Formats the given \a rLoggingEvent using the chain of
+ * PatternConverter created during construction from the specified
+ * pattern.
+ */
+ QString format(const LoggingEvent &rLoggingEvent) const;
+
+ private:
+ /*!
+ * If the character \a rDigit is a digit the digit is added to the
+ * integer \a rValue and the function returns true. Otherwise the
+ * function returns false.
+ *
+ * The function adds the digit by multiplying the existing value
+ * with ten and adding the numerical value of the digit. If the
+ * maximum integer value would be exceeded by the operation
+ * \a rValue is set to INT_MAX.
+ */
+ bool addDigit(const QChar &rDigit,
+ int &rValue);
+
+ /*!
+ * Creates a PatternConverter based on the specified conversion
+ * character \a rChar, the formatting information
+ * \a rFormattingInfo and the option \a rOption.
+ *
+ * The PatternConverter converter is appended to the list of
+ * PatternConverters.
+ */
+ void createConverter(const QChar &rChar,
+ const FormattingInfo &rFormattingInfo,
+ const QString &rOption = QString());
+
+ /*!
+ * Creates a LiteralPatternConverter with the string literal
+ * \a rLiteral.
+ *
+ * The PatternConverter converter is appended to the list of
+ * PatternConverters.
+ */
+ void createLiteralConverter(const QString &rLiteral);
+
+ /*!
+ * Parses the pattern string specified on construction and creates
+ * PatternConverter according to it.
+ */
+ void parse();
+
+ /*!
+ * Parses an integer option from an option string. If the string is
+ * not a valid integer or the integer value is less then zero, zero
+ * is returned. Returns the end of line seperator for the operating
+ * system.
+ */
+ int parseIntegerOption(const QString &rOption);
+
+ private:
+ const QString mIgnoreCharacters;
+ const QString mConversionCharacters;
+ const QString mOptionCharacters;
+ QString mPattern;
+ QList<PatternConverter *> mPatternConverters;
+
+ // Needs to be friend to access internal data
+ friend QDebug operator<<(QDebug, const PatternFormatter &rPatternFormatter);
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates PatternFormatter
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %PatternFormatter(pattern:"%r [%t] %p %c %x - %m%n"
+ * converters:(
+ * DatePatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) format: "RELATIVE" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " [" ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "THREAD_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "] " ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "LEVEL_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) ,
+ * LoggerPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) precision: 0 ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " " ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "NDC_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: " - " ) ,
+ * BasicPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) type: "MESSAGE_CONVERTER" ) ,
+ * LiteralPatternConverter(FormattingInfo(min:"0" max:"INT_MAX" left:false) literal: "" ) ) )
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const PatternFormatter &rPatternFormatter);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::PatternFormatter, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_PATTERNFORMATTER_H
diff --git a/ext/Log4Qt/src/helpers/properties.cpp b/ext/Log4Qt/src/helpers/properties.cpp
new file mode 100755
index 0000000..5bfecd0
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/properties.cpp
@@ -0,0 +1,364 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: properties.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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 "helpers/properties.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QIODevice>
+#include <QtCore/QSettings>
+#include <QtCore/QTextStream>
+#include "logger.h"
+
+
+
+namespace Log4Qt
+{
+
+
+
+ /**************************************************************************
+ *Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Properties)
+
+
+
+ /**************************************************************************
+ * Class implementation: Properties
+ **************************************************************************/
+
+
+ void Properties::load(QIODevice *pDevice)
+ {
+ const QLatin1Char append_char(msEscapeChar);
+
+ if (!pDevice)
+ {
+ logger()->warn("No device specified for load.");
+ return;
+ }
+
+ QTextStream stream(pDevice);
+ QString line;
+ int line_number = 0;
+ QString property;
+ int property_start_line = 1;
+
+ do {
+ line = trimLeft(stream.readLine());
+ line_number++;
+
+ if (!line.isEmpty() && line.at(line.length() - 1) == append_char)
+ property += line.left(line.length() - 1);
+ else
+ {
+ property += line;
+ parseProperty(property, property_start_line);
+ property.clear();
+ property_start_line = line_number + 1;
+ }
+ }
+ while (!line.isNull());
+ }
+
+
+ void Properties::load(const QSettings &rSettings)
+ {
+ QStringList keys = rSettings.childKeys();
+ QString key;
+ Q_FOREACH(key, keys)
+ insert(key, rSettings.value(key).toString());
+ }
+
+
+ QString Properties::property(const QString &rKey) const
+ {
+ // Null string indicates the property does not contain the key.
+
+ if (contains(rKey))
+ {
+ QString value = this->value(rKey);
+ if (value.isNull())
+ return QString(QLatin1String(""));
+ else
+ return value;
+ }
+
+ if (mpDefaultProperties)
+ return mpDefaultProperties->property(rKey);
+ else
+ return QString();
+ }
+
+
+ QString Properties::property(const QString &rKey,
+ const QString &rDefaultValue) const
+ {
+ QString value = property(rKey);
+ if (value.isNull())
+ return rDefaultValue;
+ else
+ return value;
+ }
+
+
+ QStringList Properties::propertyNames() const
+ {
+ QStringList default_keys;
+ if (mpDefaultProperties)
+ default_keys = mpDefaultProperties->propertyNames();
+
+ QStringList keys = this->keys();
+ QString key;
+ Q_FOREACH(key, default_keys)
+ if (!keys.contains(key))
+ keys << key;
+
+ return keys;
+ }
+
+
+ void Properties::parseProperty(const QString &rProperty,
+ int line)
+ {
+ Q_ASSERT_X(rProperty == trimLeft(rProperty), "parseProperty()", "rProperty has leading spaces");
+
+ enum State
+ {
+ KEY_STATE,
+ KEYSPACE_STATE,
+ SPACEVALUE_STATE,
+ VALUE_STATE,
+ KEYESCAPE_STATE,
+ VALUEESCAPE_STATE,
+ UNICODEESCAPE_STATE
+ };
+ const QString value_escape_codes =QLatin1String(msValueEscapeCodes);
+ const QString value_escape_chars = QLatin1String(msValueEscapeChars);
+ Q_ASSERT_X(value_escape_codes.length() == value_escape_chars.length(), "parseProperty()", "Value escape sequence character definition does not map");
+ const QString key_escape_codes = QLatin1String(msKeyEscapeCodes);
+ const QString key_escape_chars = QLatin1String(msKeyEscapeChars);
+ Q_ASSERT_X(key_escape_codes.length() == key_escape_chars.length(), "parseProperty()", "Key escape sequence character definition does not map");
+
+ if (rProperty.isEmpty())
+ return;
+
+ int i = 0;
+ QChar c;
+ char ch;
+ State state = KEY_STATE;
+ QString key;
+ QString value;
+ QString *p_string = &key;
+ uint ucs = 0;
+ int ucs_digits = 0;
+ while (i < rProperty.length())
+ {
+ // i points to the current character.
+ // c contains the current character
+ // ch contains the Latin1 equivalent of the current character
+ // i is incremented at the end of the loop to consume the character.
+ // continue is used to change state without consuming the character
+
+ c = rProperty.at(i);
+ ch = c.toLatin1();
+
+ switch (state)
+ {
+ case KEY_STATE:
+ if (ch == '!' || ch == '#' )
+ return;
+ else if (c.isSpace())
+ {
+ p_string = &value;
+ state = KEYSPACE_STATE;
+ }
+ else if (ch == '=' || ch == ':')
+ {
+ p_string = &value;
+ state = SPACEVALUE_STATE;
+ }
+ else if (ch == msEscapeChar)
+ state = KEYESCAPE_STATE;
+ else
+ *p_string += c;
+ break;
+ case KEYSPACE_STATE:
+ if (ch == '=' || ch == ':')
+ state = SPACEVALUE_STATE;
+ else if (!c.isSpace())
+ {
+ *p_string += c;
+ state = VALUE_STATE;
+ }
+ break;
+ case SPACEVALUE_STATE:
+ if (!c.isSpace())
+ {
+ *p_string += c;
+ state = VALUE_STATE;
+ }
+ break;
+ case VALUE_STATE:
+ if (ch == msEscapeChar)
+ state = VALUEESCAPE_STATE;
+ else
+ *p_string += c;
+ break;
+ case KEYESCAPE_STATE:
+ {
+ int convert = key_escape_codes.indexOf(c);
+ if (convert >= 0)
+ *p_string += key_escape_chars.at(convert);
+ else
+ {
+ logger()->warn("Unknown escape sequence '\\%1' in key of property starting at line %2",
+ QString(c),
+ line);
+ *p_string += c;
+ }
+ state = KEY_STATE;
+ break;
+ }
+ case VALUEESCAPE_STATE:
+ {
+ int convert = value_escape_codes.indexOf(c);
+ if (convert >= 0)
+ {
+ *p_string += value_escape_chars.at(convert);
+ state = VALUE_STATE;
+ }
+ else if (ch == 'u')
+ {
+ ucs = 0;
+ ucs_digits = 0;
+ state = UNICODEESCAPE_STATE;
+ }
+ else
+ {
+ logger()->warn("Unknown escape sequence '\\%1' in value of property starting at line %2", QString(c), line);
+ *p_string += c;
+ state = VALUE_STATE;
+ }
+ break;
+ }
+ case UNICODEESCAPE_STATE:
+ {
+ int hex = hexDigitValue(c);
+ if (hex >= 0)
+ {
+ ucs = ucs * 16 + hex;
+ ucs_digits++;
+ if (ucs_digits == 4 || i == rProperty.length() - 1)
+ {
+ *p_string += QChar(ucs);
+ state = VALUE_STATE;
+ }
+ }
+ else
+ {
+ if (ucs_digits > 0)
+ *p_string += QChar(ucs);
+ state = VALUE_STATE;
+ continue;
+ }
+ break;
+ }
+ default:
+ Q_ASSERT_X(false, "Properties::parseProperty()", "Unknown state constant");
+ return;
+ }
+ i++;
+ }
+
+ if (key.isEmpty() && !value.isEmpty())
+ logger()->warn("Found value with no key in property starting at line %1", line);
+
+ logger()->trace("Loaded property '%1' : '%2'", key, value);
+ insert(key, value);
+ }
+
+
+ int Properties::hexDigitValue(const QChar &rDigit)
+ {
+ bool ok;
+ int result = QString(rDigit).toInt(&ok, 16);
+ if (!ok)
+ return -1;
+ else
+ return result;
+ }
+
+
+ QString Properties::trimLeft(const QString &rLine)
+ {
+ int i = 0;
+ while (i < rLine.length() && rLine.at(i).isSpace())
+ i++;
+ return rLine.right(rLine.length() - i);
+ }
+
+
+ const char Properties::msEscapeChar ='\\';
+ const char *Properties::msValueEscapeCodes = "tnr\\\"\' ";
+ const char *Properties::msValueEscapeChars = "\t\n\r\\\"\' ";
+ const char *Properties::msKeyEscapeCodes = " :=";
+ const char *Properties::msKeyEscapeChars = " :=";
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const Properties &rProperties)
+ {
+ debug.nospace() << "Properties("
+ << "default:" << rProperties.defaultProperties() << " "
+ << "properties:" << *reinterpret_cast<const QHash <QString, QString > *>(&rProperties)
+ << ")";
+ return debug.space();
+ }
+#endif
+
+
+
+} // namespace Log4Qt
diff --git a/ext/Log4Qt/src/helpers/properties.h b/ext/Log4Qt/src/helpers/properties.h
new file mode 100755
index 0000000..0866431
--- /dev/null
+++ b/ext/Log4Qt/src/helpers/properties.h
@@ -0,0 +1,161 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: properties.h
+ * created: September
+ * author: Martin Heinrich
+ *
+ *
+ * Copyright 2007 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.
+ *
+ ******************************************************************************/
+
+#ifndef LOG4QT_PROPERTIES_H
+#define LOG4QT_PROPERTIES_H
+
+#include "../log4qtshared.h"
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+#include <QtCore/QHash>
+#include <QtCore/QStringList>
+
+
+/******************************************************************************
+ * Declarations
+ ******************************************************************************/
+
+class QIODevice;
+class QSettings;
+
+
+namespace Log4Qt
+{
+ /*!
+ * \brief The class Properties implements a JAVA property hash.
+ */
+ class LOG4QT_EXPORT Properties : public QHash<QString, QString>
+ {
+ public:
+ Properties(Properties *pDefaultProperties = 0);
+ // virtual ~Properties(); // Use compiler default
+ // Properties(const Properties &rOther); // Use compiler default
+ // Properties &operator=(const Properties &rOther); // Not implemented
+
+ public:
+ Properties *defaultProperties() const;
+ QString property(const QString &rKey) const;
+ QString property(const QString &rKey,
+ const QString &rDefaultValue) const;
+ void setDefaultProperties(Properties *pDefault);
+ void setProperty(const QString &rKey,
+ const QString &rValue);
+
+ // JAVA: void list(QTextStream &rTextStream);
+ void load(QIODevice *pDevice);
+
+ /*!
+ * Reads all child keys from the QSettings object \a rSettings and
+ * inserts them into this object. The value is created using
+ * QVariant::toString(). Types that do not support toString() are
+ * resulting in an empty string.
+ *
+ * \code
+ * QSettings settings;
+ * settings.setValue("Package", "Full");
+ * settings.setValue("Background", Qt::white);
+ * settings.setValue("Support", true);
+ * settings.setValue("Help/Language", "en_UK");
+ *
+ * Properties properties
+ * properties.load(&settings)
+ *
+ * // properties (("Package", "Full"), ("Background", ""), ("Support", "true"))
+ * \endcode
+ */
+ void load(const QSettings &rSettings);
+
+ QStringList propertyNames() const;
+ // JAVA: void save(QIODevice *pDevice) const;
+
+ private:
+ void parseProperty(const QString &rProperty,
+ int line);
+ static int hexDigitValue(const QChar &rDigit);
+ static QString trimLeft(const QString &rString);
+
+ private:
+ Properties *mpDefaultProperties;
+ static const char msEscapeChar;
+ static const char *msValueEscapeCodes;
+ static const char *msValueEscapeChars;
+ static const char *msKeyEscapeCodes;
+ static const char *msKeyEscapeChars;
+ };
+
+
+ /**************************************************************************
+ * Operators, Helper
+ **************************************************************************/
+
+#ifndef QT_NO_DEBUG_STREAM
+ /*!
+ * \relates Properties
+ *
+ * Writes all object member variables to the given debug stream \a rDebug and
+ * returns the stream.
+ *
+ * <tt>
+ * %Properties(default:0x0 properties:QHash(("log4j.appender.testAppender.layout", "org.apache.log4j.PatternLayout ")
+ * ("log4j.appender.testAppender.layout.ConversionPattern", "[%t] %-5p %l: %m%n")
+ * ("log4j.appender.testAppender.Append", "false ")
+ * ("log4j.appender.testAppender.File", "output/temp ")
+ * ("log4j.rootCategory", "TRACE, testAppender")
+ * ("log4j.appender.testAppender", "org.apache.log4j.FileAppender")) )
+ * </tt>
+ * \sa QDebug
+ */
+ QDebug operator<<(QDebug debug,
+ const Properties &rProperties);
+#endif // QT_NO_DEBUG_STREAM
+
+
+ /**************************************************************************
+ * Inline
+ **************************************************************************/
+
+ inline Properties::Properties(Properties *pDefaultProperties) :
+ mpDefaultProperties(pDefaultProperties)
+ {}
+
+ inline Properties *Properties::defaultProperties() const
+ { return mpDefaultProperties; }
+
+ inline void Properties::setDefaultProperties(Properties *pDefaultProperties)
+ { mpDefaultProperties = pDefaultProperties; }
+
+ inline void Properties::setProperty(const QString &rKey,
+ const QString &rValue)
+ { insert(rKey, rValue); }
+
+
+} // namespace Log4Qt
+
+
+Q_DECLARE_TYPEINFO(Log4Qt::Properties, Q_MOVABLE_TYPE);
+
+
+#endif // LOG4QT_PROPERTIES_H