diff options
| author | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-11 21:06:39 +0200 |
|---|---|---|
| committer | Tomasz Sterna <tomek@xiaoka.com> | 2014-07-11 21:06:39 +0200 |
| commit | efb33d6494d88c27c8766553b6a963ddf2654458 (patch) | |
| tree | 76dd5e56b79191074998c0fb6bf7b81276116a4b | |
| parent | 072da88eee57e5d16f0b75c7b90c8a0bc6a60cb3 (diff) | |
Included Log4Qt in project
153 files changed, 22589 insertions, 6 deletions
diff --git a/app/app.pro b/app/app.pro index 40a4a1d..48aff06 100644 --- a/app/app.pro +++ b/app/app.pro @@ -2,6 +2,9 @@ TARGET = pebble CONFIG += sailfishapp +QT += dbus +QMAKE_CXXFLAGS += -std=c++0x + SOURCES += \ pebble.cpp \ pebbledinterface.cpp @@ -9,9 +12,6 @@ SOURCES += \ HEADERS += \ pebbledinterface.h -QT += dbus -QMAKE_CXXFLAGS += -std=c++0x - OTHER_FILES += \ qml/cover/CoverPage.qml \ qml/pages/ManagerPage.qml \ diff --git a/daemon/daemon.pro b/daemon/daemon.pro index deadea0..aca65f1 100644 --- a/daemon/daemon.pro +++ b/daemon/daemon.pro @@ -9,6 +9,10 @@ QT += bluetooth dbus contacts PKGCONFIG += commhistory-qt5 mlite5 QMAKE_CXXFLAGS += -std=c++0x +LIBS += -L$$OUT_PWD/../ext/Log4Qt/ -llog4qt +QMAKE_RPATHDIR += /usr/share/$$TARGET/lib +INCLUDEPATH += ../ext/Log4Qt/src ../ext/Log4Qt/deploy/include + SOURCES += \ daemon.cpp \ manager.cpp \ @@ -26,11 +30,30 @@ HEADERS += \ dbusconnector.h \ dbusadaptor.h -INSTALLS += target pebbled +OTHER_FILES += \ + org.pebbled.xml \ + ../log4qt-debug.conf \ + ../log4qt-release.conf + +INSTALLS += target pebbled config target.path = /usr/bin pebbled.files = $${TARGET}.service pebbled.path = /usr/lib/systemd/user -OTHER_FILES += org.pebbled.xml +CONFIG(debug, debug|release) { + message(Debug build) + log4qt_demo_config.extra = cp $$PWD/../../log4qt-debug.conf $$OUT_PWD/../../log4qt.conf +} +else { + message(Release build) + log4qt_demo_config.extra = cp $$PWD/../../log4qt-release.conf $$OUT_PWD/../../log4qt.conf +} + +config.files = $$OUT_PWD/../../log4qt.conf +config.path = /usr/share/$$TARGET + +# so QtCreator could find commhistory headers... :-( +INCLUDEPATH += $$[QT_HOST_PREFIX]/include/commhistory-qt5 +INCLUDEPATH += $$[QT_HOST_PREFIX]/include/mlite5 diff --git a/ext/Log4Qt/.gitignore b/ext/Log4Qt/.gitignore new file mode 100644 index 0000000..9c02ba4 --- /dev/null +++ b/ext/Log4Qt/.gitignore @@ -0,0 +1,74 @@ +doc/html/ +sql/ +winbuild/ +build/ +*.dll +!doc/src +bin/ +lib/ + +# object files +*.[oa] +*.so +*.so.* + +# qt creator projects +*.cbp +*.user + +# qt creator cmake directories +qt-creator*/ +qtcreator*/ + +# manually cmake build directories +build*/ + +# win32 libs +*.dll +# win32 impl +*.lib + +# temporary dirs +tmp/ + +# logger dirs +log/ + +# html docs because it's generated by doxygen +doc/html/ + +# test +test/ +test*/ + +# qmake mocs +moc_*.cpp + +# qt ui headers +ui*.h + +# qt translations files +*.qm + +# temporary files +*~ + +# emacs temporary files +##*## + +# make files +Makefile + +# cmake build system +CMakeFiles/ +CMakeCache.txt + +# cmake mocs +moc*.cxx +*.moc + +# include cmake build file +#!CMakeLists.txt + +#Doxygen file generated by cmake +Doxyfile
\ No newline at end of file diff --git a/ext/Log4Qt/CMakeLists.txt b/ext/Log4Qt/CMakeLists.txt new file mode 100755 index 0000000..81773e2 --- /dev/null +++ b/ext/Log4Qt/CMakeLists.txt @@ -0,0 +1,300 @@ +cmake_minimum_required(VERSION 2.6) + +# cmake options +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/lib") +# postfix for library +set(CMAKE_DEBUG_POSTFIX d) +set(CMAKE_INCLUDE_CURRENT_DIR TRUE) +# variable for project name, used in many places +set (PROJECT Log4Qt) + +project(${PROJECT}) + +string(TOUPPER ${PROJECT_NAME} PROJECT_TO_UPPER) +string(TOLOWER ${PROJECT_NAME} PROJECT_TO_LOWER) + +find_package(Qt4 REQUIRED) +# COMPILER customization + # compilers flags + if (MSVC) + add_definitions (/W3 -Zc:wchar_t-) + elseif (CMAKE_COMPILER_IS_GNUCXX) + add_definitions (-Wall) + else () + message ("Unknown compiler") + endif () + #compiler options + set(OPTIMIZATION_FLAGS "-O2" ) +message("Building project ${PROJECT_NAME}") + +message(" +Configuration +------------- +CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE} +CXXFLAGS = $ENV{CXXFLAGS} +CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS} +LDFLAGS = $ENV{LDFLAGS} +CMAKE_EXE_LINKER_FLAGS = ${CMAKE_EXE_LINKER_FLAGS} +CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX} +") + +# remove when release +if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") + set(CMAKE_VERBOSE_MAKEFILE TRUE) +endif (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release") + +# SOURCE FILES AND DIRECTORIES +set(LOG4QT_SOURCES) +# Q_SOURCES, var contains files, for which need call qt4_automoc +set(LOG4QT_Q_SOURCES) +set(LOG4QT_HEADERS) +# Q_HEADERS, var contains files, for which qt4_wrap_cpp called +set(LOG4QT_Q_HEADERS) + +set(LOG4QT_HEADERS + src/basicconfigurator.h + src/helpers/classlogger.h + src/helpers/datetime.h + src/helpers/factory.h + src/hierarchy.h + src/helpers/initialisationhelper.h + src/level.h + src/log4qt.h + src/log4qtshared.h + src/loggerrepository.h + src/loggingevent.h + src/logmanager.h + src/helpers/logobjectptr.h + src/mdc.h + src/ndc.h + src/helpers/optionconverter.h + src/helpers/patternformatter.h + src/helpers/properties.h + src/propertyconfigurator.h + src/helpers/logerror.h + src/helpers/appenderattachable.h + src/logstream.h +) + +set(LOG4QT_Q_HEADERS src/appender.h + src/appenderskeleton.h + src/asyncappender.h + src/colorconsoleappender.h + src/consoleappender.h + src/dailyrollingfileappender.h + src/fileappender.h + src/mainthreadappender.h + src/layout.h + src/logger.h + src/patternlayout.h + src/rollingfileappender.h + src/signalappender.h + src/simplelayout.h + src/simpletimelayout.h + src/ttcclayout.h + src/writerappender.h + src/systemlogappender.h + src/helpers/configuratorhelper.h + src/helpers/logobject.h + src/helpers/dispatcher.h + src/spi/filter.h + src/varia/debugappender.h + src/varia/denyallfilter.h + src/varia/levelmatchfilter.h + src/varia/levelrangefilter.h + src/varia/listappender.h + src/varia/nullappender.h + src/varia/stringmatchfilter.h) + +set(LOG4QT_SOURCES + src/helpers/classlogger.cpp + src/helpers/configuratorhelper.cpp + src/helpers/datetime.cpp + src/helpers/factory.cpp + src/helpers/initialisationhelper.cpp + src/helpers/logerror.cpp + src/helpers/logobject.cpp + src/helpers/dispatcher.cpp + src/helpers/logobjectptr.cpp + src/helpers/optionconverter.cpp + src/helpers/patternformatter.cpp + src/helpers/properties.cpp + src/helpers/appenderattachable.cpp + src/spi/filter.cpp + src/varia/debugappender.cpp + src/varia/denyallfilter.cpp + src/varia/levelmatchfilter.cpp + src/varia/levelrangefilter.cpp + src/varia/listappender.cpp + src/varia/nullappender.cpp + src/varia/stringmatchfilter.cpp + src/systemlogappender.cpp + src/appenderskeleton.cpp + src/basicconfigurator.cpp + src/colorconsoleappender.cpp + src/consoleappender.cpp + src/asyncappender.cpp + src/dailyrollingfileappender.cpp + src/fileappender.cpp + src/mainthreadappender.cpp + src/hierarchy.cpp + src/layout.cpp + src/level.cpp + src/log4qt.cpp + src/logger.cpp + src/loggerrepository.cpp + src/loggingevent.cpp + src/logmanager.cpp + src/mdc.cpp + src/ndc.cpp + src/patternlayout.cpp + src/propertyconfigurator.cpp + src/rollingfileappender.cpp + src/signalappender.cpp + src/simplelayout.cpp + src/simpletimelayout.cpp + src/ttcclayout.cpp + src/writerappender.cpp + src/logstream.cpp +) + +# project version +set(LOG4QT_VERSION_MAJOR 1) +set(LOG4QT_VERSION_MINOR 0) +set(LOG4QT_VERSION_RELEASE 0) +set(LOG4QT_VERSION "${LOG4QT_VERSION_MAJOR}.${LOG4QT_VERSION_MINOR}.${LOG4QT_VERSION_RELEASE}") +set(VERSION ${LOG4QT_VERSION}) +set(SOVERSION ${LOG4QT_VERSION}) +add_definitions(-DLOG4QT_VERSION=${LOG4QT_VERSION_MAJOR}*65536+${LOG4QT_VERSION_MINOR}*256+${LOG4QT_VERSION_RELEASE}) +add_definitions(-DLOG4QT_VERSION_STR="${LOG4QT_VERSION}") + +# Make sure LOG4QT_BUILD_STATIC is defined since the variable value is used when configuring +# the project-config.cmake file. +if (NOT DEFINED LOG4QT_BUILD_STATIC) + set (LOG4QT_BUILD_STATIC FALSE) +endif (NOT DEFINED LOG4QT_BUILD_STATIC) + +# QT +set(QT_DONT_USE_QTGUI TRUE) +include(${QT_USE_FILE}) + +if (QT_USE_QTSQL) + message("With QT_USE_QTSQL DatabaseAppender, DatabaseLayout compiled") + list(APPEND LOG4QT_Q_HEADERS src/databaseappender.h src/databaselayout.h) + list(APPEND LOG4QT_SOURCES src/databaseappender.cpp src/databaselayout.cpp) +endif (QT_USE_QTSQL) + +if (QT_USE_QTNETWORK) + message("With QT_USE_QTNETWORK TelnetAppender compiled") + list(APPEND LOG4QT_Q_HEADERS src/telnetappender.h ) + list(APPEND LOG4QT_SOURCES src/telnetappender.cpp) +endif (QT_USE_QTNETWORK) + +include_directories(src) + +# COMPILATION +# if you use Q_OBJECT +qt4_wrap_cpp(LOG4QT_MOC_SOURCES ${LOG4QT_Q_HEADERS}) +qt4_automoc(${LOG4QT_Q_SOURCES}) + +# BUILD STATIC LIBRARY +if (LOG4QT_BUILD_STATIC) +set(LOG4QT_BUILD_CONFIGURATION STATIC) +# BUILD SHARED LIBRARY +else (LOG4QT_BUILD_STATIC) +set(LOG4QT_BUILD_CONFIGURATION SHARED) +endif (LOG4QT_BUILD_STATIC) + +add_library(${PROJECT_NAME} ${LOG4QT_BUILD_CONFIGURATION} + ${LOG4QT_SOURCES} + ${LOG4QT_Q_SOURCES} + ${LOG4QT_MOC_SOURCES} + ${LOG4QT_HEADERS} + ${LOG4QT_Q_HEADERS}) + +# LINKING +target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES}) + +set_target_properties(${PROJECT_NAME} PROPERTIES + SOVERSION ${LOG4QT_VERSION} + VERSION ${LOG4QT_VERSION} + DEFINE_SYMBOL ${PROJECT_TO_UPPER}_EXPORTS) + +# Allow install location to be overridden for libraries, includes, binaries and cmake configuration +# files. This provides fine-grained control over where various pieces get installed. The +# LIB_INSTALL_DIR and BIN_INSTALL_DIR locations are particularly useful for platforms where 32-bit +# and 64-bit binaries must be separate. (Idea shamelessly stolen from the QJson project.) +# NOTE: these locations will be used *only* if CMAKE_INSTALL_PREFIX is explicitly defined (see +# comment below). +set (BIN_SUFFIX "" CACHE STRING "Define suffix of binary directory name (32/64)" ) +set (BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin${BIN_SUFFIX}" CACHE PATH "The directory where binaries will install") +set (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${BIN_SUFFIX}" CACHE PATH "The directory where lib will install") +set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/${PROJECT_TO_LOWER}" CACHE PATH "The directory where headers will install") +set (CMAKECONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME}" CACHE PATH "The directory where Log4QtConfig.cmake will install") + +if (NOT LOG4QT_DONT_INSTALL) + + # The original implementation of this module used hardcoded paths for the install locations on + # Mac OS X (everything was installed under the /usr directory); or would install directly into + # the Qt directories on other platforms. CMAKE_INSTALL_PREFIX was ignored. This original + # behaviour is preserved for anyone who was relying on it. We continue to use those default + # install locations if CMAKE_INSTALL_PREFIX has *not* been explicitly defined. The rationale is + # that folks who were satisfied with the old, default install locations would not have been + # trying to use CMAKE_INSTALL_PREFIX. + if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + if (NOT APPLE) + SET(TARGET_INCLUDE_DIR "${QT_INCLUDE_DIR}/${PROJECT_NAME}") + SET(TARGET_LIB_DIR "${QT_LIBRARY_DIR}") + SET(TARGET_BIN_DIR "${QT_BINARY_DIR}") + else() + #Qt is the framework but log4qt is not. So it should not be placed into the frameworks location + #Also the include dir should not be retrieved from the Qt itself, see http://www.paraview.org/Bug/view.php?id=10632 + SET(TARGET_INCLUDE_DIR "/usr/include/${PROJECT_NAME}") + SET(TARGET_LIB_DIR "/usr/lib") + SET(TARGET_BIN_DIR "/usr/bin") + endif() + # copy project file into qt_libdir and create project.cmake file for use this library in your cmake projects + set(EXPORT_TARGET_DESTINATION "${QT_MKSPECS_DIR}/cmake/${PROJECT_NAME}") + else() + SET(TARGET_INCLUDE_DIR "${INCLUDE_INSTALL_DIR}") + SET(TARGET_LIB_DIR "${LIB_INSTALL_DIR}") + SET(TARGET_BIN_DIR "${BIN_INSTALL_DIR}") + SET(EXPORT_TARGET_DESTINATION "${CMAKECONFIG_INSTALL_DIR}") + endif (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + + # for using library in your cmake projects + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/project-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_TO_LOWER}-config.cmake" + IMMEDIATE @ONLY) + + # INSTALLATION + # install and export project target + set(PROJECT_TARGETS ${PROJECT_NAME}-targets) + + install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_TARGETS} + RUNTIME DESTINATION ${TARGET_BIN_DIR} + LIBRARY DESTINATION ${TARGET_LIB_DIR} + ARCHIVE DESTINATION ${TARGET_LIB_DIR}) + + # install exported project target cmake file into export target + install(EXPORT ${PROJECT_TARGETS} DESTINATION ${EXPORT_TARGET_DESTINATION} COMPONENT Devel) + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/" DESTINATION "${TARGET_INCLUDE_DIR}" COMPONENT Devel + FILES_MATCHING PATTERN "*.h") + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/deploy/include/" DESTINATION "${TARGET_INCLUDE_DIR}" COMPONENT Devel) + + # install cmake config file + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_TO_LOWER}-config.cmake DESTINATION ${EXPORT_TARGET_DESTINATION} COMPONENT Devel) + + # UNINSTALL TARGET + # create cmake uninstall files and unregister docs scripts + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +endif (NOT LOG4QT_DONT_INSTALL) diff --git a/ext/Log4Qt/Log4Qt.pro b/ext/Log4Qt/Log4Qt.pro new file mode 100644 index 0000000..65700d2 --- /dev/null +++ b/ext/Log4Qt/Log4Qt.pro @@ -0,0 +1,21 @@ + +include(src/Log4Qt.pri) + +TEMPLATE = lib +QT += core xml network +TARGET = log4qt + +LOG4QT_VERSION_MAJOR = 1 +LOG4QT_VERSION_MINOR = 1 +LOG4QT_VERSION_RELEASE = 0 + +LOG4QT_VERSION = '\\"$${LOG4QT_VERSION_MAJOR}.$${LOG4QT_VERSION_MINOR}.$${LOG4QT_VERSION_RELEASE}\\"' +DEFINES += LOG4QT_VERSION_STR=\"$${LOG4QT_VERSION}\" +DEFINES += LOG4QT_VERSION=$${LOG4QT_VERSION} + +VERSION = 1.1.0 + +DEPENDPATH += src src/helpers src/spisrc/ varia +INCLUDEPATH += src src/helpers src/spi src/varia + + diff --git a/ext/Log4Qt/Readme.txt b/ext/Log4Qt/Readme.txt new file mode 100644 index 0000000..61ddd8f --- /dev/null +++ b/ext/Log4Qt/Readme.txt @@ -0,0 +1,51 @@ +Build and install + +*NIX + STATIC + cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release -DLOG4QT_BUILD_STATIC=True . + make + make install + SHARED + cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release . + make + make install + +WIN* + STATIC + cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" -DLOG4QT_BUILD_STATIC=True . + mingw32-make + mingw32-make install + SHARED + cmake -DQT_USE_QTSQL=TRUE -DQT_USE_QTNETWORK=TRUE -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" . + mingw32-make + mingw32-make install + +If you dont want to use log4qt sql features you must not define QT_USE_QTSQL. +If you dont want to use log4qt network features you must not define QT_USE_QTNETWORK. + +Using in your projects + +If your have cmake-based project + for shared linking you must: + 1. make log4qt in shared mode; + 2. install it; + 1. add log4qt package to your CMakeLists.txt; + 2. include header directory; + 3. link library to target. + + For example: + find_package(log4qt REQUIRED HINTS "${QT_MKSPECS_DIR}/cmake/Log4Qt" NO_DEFAULT_PATHS) + include_directories(${LOG4QT_INCLUDE_DIRS}) + target_link_libraries(main ${QT_LIBRARIES} log4qt) + + for static linking: + 1. add subdirectory to your project + 2. include log4qt/src + 3. link library to target + + For example: + add_subdirectory(../log4qt ${CMAKE_CURRENT_BINARY_DIR}/log4qt) + include_directories(../log4qt/src) + target_link_libraries(main ${QT_LIBRARIES} log4qt) + + diff --git a/ext/Log4Qt/cmake_uninstall.cmake.in b/ext/Log4Qt/cmake_uninstall.cmake.in new file mode 100644 index 0000000..65750dd --- /dev/null +++ b/ext/Log4Qt/cmake_uninstall.cmake.in @@ -0,0 +1,22 @@ + +IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +STRING(REGEX REPLACE "\n" ";" files "${files}") +FOREACH(file ${files}) + MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") +# IF(EXISTS "$ENV{DESTDIR}${file}") + EXEC_PROGRAM( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + IF(NOT "${rm_retval}" STREQUAL 0) + MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + ENDIF(NOT "${rm_retval}" STREQUAL 0) +# ELSE(EXISTS "$ENV{DESTDIR}${file}") +# MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") +# ENDIF(EXISTS "$ENV{DESTDIR}${file}") +ENDFOREACH(file) diff --git a/ext/Log4Qt/deploy/include/Appender b/ext/Log4Qt/deploy/include/Appender new file mode 100644 index 0000000..d6dc380 --- /dev/null +++ b/ext/Log4Qt/deploy/include/Appender @@ -0,0 +1 @@ +#include "appender.h" diff --git a/ext/Log4Qt/deploy/include/Appenderskeleton b/ext/Log4Qt/deploy/include/Appenderskeleton new file mode 100644 index 0000000..a00c2bb --- /dev/null +++ b/ext/Log4Qt/deploy/include/Appenderskeleton @@ -0,0 +1 @@ +#include "appenderskeleton.h" diff --git a/ext/Log4Qt/deploy/include/AsyncAppender b/ext/Log4Qt/deploy/include/AsyncAppender new file mode 100644 index 0000000..244f918 --- /dev/null +++ b/ext/Log4Qt/deploy/include/AsyncAppender @@ -0,0 +1 @@ +#include "asyncappender.h" diff --git a/ext/Log4Qt/deploy/include/BasicConfigurator b/ext/Log4Qt/deploy/include/BasicConfigurator new file mode 100644 index 0000000..72d6d38 --- /dev/null +++ b/ext/Log4Qt/deploy/include/BasicConfigurator @@ -0,0 +1 @@ +#include "basicconfigurator.h" diff --git a/ext/Log4Qt/deploy/include/ColorConsoleAppender b/ext/Log4Qt/deploy/include/ColorConsoleAppender new file mode 100644 index 0000000..70e6126 --- /dev/null +++ b/ext/Log4Qt/deploy/include/ColorConsoleAppender @@ -0,0 +1 @@ +#include "colorconsoleappender.h" diff --git a/ext/Log4Qt/deploy/include/ConsoleAppender b/ext/Log4Qt/deploy/include/ConsoleAppender new file mode 100644 index 0000000..16132b1 --- /dev/null +++ b/ext/Log4Qt/deploy/include/ConsoleAppender @@ -0,0 +1 @@ +#include "consoleappender.h" diff --git a/ext/Log4Qt/deploy/include/DailyRollingFileAppender b/ext/Log4Qt/deploy/include/DailyRollingFileAppender new file mode 100644 index 0000000..0b655e0 --- /dev/null +++ b/ext/Log4Qt/deploy/include/DailyRollingFileAppender @@ -0,0 +1 @@ +#include "dailyrollingfileappender.h" diff --git a/ext/Log4Qt/deploy/include/DatabaseAppender b/ext/Log4Qt/deploy/include/DatabaseAppender new file mode 100644 index 0000000..9f08924 --- /dev/null +++ b/ext/Log4Qt/deploy/include/DatabaseAppender @@ -0,0 +1 @@ +#include "databaseappender.h" diff --git a/ext/Log4Qt/deploy/include/DatabaseLayout b/ext/Log4Qt/deploy/include/DatabaseLayout new file mode 100644 index 0000000..2b9c0c4 --- /dev/null +++ b/ext/Log4Qt/deploy/include/DatabaseLayout @@ -0,0 +1 @@ +#include "databaselayout.h" diff --git a/ext/Log4Qt/deploy/include/FileAppender b/ext/Log4Qt/deploy/include/FileAppender new file mode 100644 index 0000000..60ff85e --- /dev/null +++ b/ext/Log4Qt/deploy/include/FileAppender @@ -0,0 +1 @@ +#include "fileappender.h" diff --git a/ext/Log4Qt/deploy/include/Hierarchy b/ext/Log4Qt/deploy/include/Hierarchy new file mode 100644 index 0000000..e48fdae --- /dev/null +++ b/ext/Log4Qt/deploy/include/Hierarchy @@ -0,0 +1 @@ +#include "hierarchy.h" diff --git a/ext/Log4Qt/deploy/include/Layout b/ext/Log4Qt/deploy/include/Layout new file mode 100644 index 0000000..34b7a35 --- /dev/null +++ b/ext/Log4Qt/deploy/include/Layout @@ -0,0 +1 @@ +#include "layout.h" diff --git a/ext/Log4Qt/deploy/include/Level b/ext/Log4Qt/deploy/include/Level new file mode 100644 index 0000000..81f1d33 --- /dev/null +++ b/ext/Log4Qt/deploy/include/Level @@ -0,0 +1 @@ +#include "level.h" diff --git a/ext/Log4Qt/deploy/include/Log4Qt b/ext/Log4Qt/deploy/include/Log4Qt new file mode 100644 index 0000000..ca511fd --- /dev/null +++ b/ext/Log4Qt/deploy/include/Log4Qt @@ -0,0 +1 @@ +#include "log4qt.h" diff --git a/ext/Log4Qt/deploy/include/Log4QtShared b/ext/Log4Qt/deploy/include/Log4QtShared new file mode 100644 index 0000000..c519afc --- /dev/null +++ b/ext/Log4Qt/deploy/include/Log4QtShared @@ -0,0 +1 @@ +#include "log4qtshared.h" diff --git a/ext/Log4Qt/deploy/include/LogManager b/ext/Log4Qt/deploy/include/LogManager new file mode 100644 index 0000000..bb4b529 --- /dev/null +++ b/ext/Log4Qt/deploy/include/LogManager @@ -0,0 +1 @@ +#include "logmanager.h" diff --git a/ext/Log4Qt/deploy/include/LogStream b/ext/Log4Qt/deploy/include/LogStream new file mode 100644 index 0000000..90f7263 --- /dev/null +++ b/ext/Log4Qt/deploy/include/LogStream @@ -0,0 +1 @@ +#include "logstream.h" diff --git a/ext/Log4Qt/deploy/include/Logger b/ext/Log4Qt/deploy/include/Logger new file mode 100644 index 0000000..86198b3 --- /dev/null +++ b/ext/Log4Qt/deploy/include/Logger @@ -0,0 +1 @@ +#include "logger.h" diff --git a/ext/Log4Qt/deploy/include/LoggerRepository b/ext/Log4Qt/deploy/include/LoggerRepository new file mode 100644 index 0000000..eb21725 --- /dev/null +++ b/ext/Log4Qt/deploy/include/LoggerRepository @@ -0,0 +1 @@ +#include "loggerrepository.h" diff --git a/ext/Log4Qt/deploy/include/LoggingEvent b/ext/Log4Qt/deploy/include/LoggingEvent new file mode 100644 index 0000000..93128b4 --- /dev/null +++ b/ext/Log4Qt/deploy/include/LoggingEvent @@ -0,0 +1 @@ +#include "loggingevent.h" diff --git a/ext/Log4Qt/deploy/include/MDC b/ext/Log4Qt/deploy/include/MDC new file mode 100644 index 0000000..80f077f --- /dev/null +++ b/ext/Log4Qt/deploy/include/MDC @@ -0,0 +1 @@ +#include "mdc.h" diff --git a/ext/Log4Qt/deploy/include/MainthreadAppender b/ext/Log4Qt/deploy/include/MainthreadAppender new file mode 100644 index 0000000..ca3fcec --- /dev/null +++ b/ext/Log4Qt/deploy/include/MainthreadAppender @@ -0,0 +1 @@ +#include "mainthreadappender.h" diff --git a/ext/Log4Qt/deploy/include/NDC b/ext/Log4Qt/deploy/include/NDC new file mode 100644 index 0000000..3c4e33b --- /dev/null +++ b/ext/Log4Qt/deploy/include/NDC @@ -0,0 +1 @@ +#include "ndc.h" diff --git a/ext/Log4Qt/deploy/include/PatternLayout b/ext/Log4Qt/deploy/include/PatternLayout new file mode 100644 index 0000000..e611ff3 --- /dev/null +++ b/ext/Log4Qt/deploy/include/PatternLayout @@ -0,0 +1 @@ +#include "patternlayout.h" diff --git a/ext/Log4Qt/deploy/include/PropertyConfigurator b/ext/Log4Qt/deploy/include/PropertyConfigurator new file mode 100644 index 0000000..d7a7664 --- /dev/null +++ b/ext/Log4Qt/deploy/include/PropertyConfigurator @@ -0,0 +1 @@ +#include "propertyconfigurator.h" diff --git a/ext/Log4Qt/deploy/include/RollingFileAppender b/ext/Log4Qt/deploy/include/RollingFileAppender new file mode 100644 index 0000000..f537b6e --- /dev/null +++ b/ext/Log4Qt/deploy/include/RollingFileAppender @@ -0,0 +1 @@ +#include "rollingfileappender.h" diff --git a/ext/Log4Qt/deploy/include/SignalAppender b/ext/Log4Qt/deploy/include/SignalAppender new file mode 100644 index 0000000..154dd55 --- /dev/null +++ b/ext/Log4Qt/deploy/include/SignalAppender @@ -0,0 +1 @@ +#include "signalappender.h" diff --git a/ext/Log4Qt/deploy/include/SimpleLayout b/ext/Log4Qt/deploy/include/SimpleLayout new file mode 100644 index 0000000..a9d929f --- /dev/null +++ b/ext/Log4Qt/deploy/include/SimpleLayout @@ -0,0 +1 @@ +#include "simplelayout.h" diff --git a/ext/Log4Qt/deploy/include/SimpleTimeLayout b/ext/Log4Qt/deploy/include/SimpleTimeLayout new file mode 100644 index 0000000..706fd72 --- /dev/null +++ b/ext/Log4Qt/deploy/include/SimpleTimeLayout @@ -0,0 +1 @@ +#include "simpletimelayout.h" diff --git a/ext/Log4Qt/deploy/include/SystemlogAppender b/ext/Log4Qt/deploy/include/SystemlogAppender new file mode 100644 index 0000000..7e9ade3 --- /dev/null +++ b/ext/Log4Qt/deploy/include/SystemlogAppender @@ -0,0 +1 @@ +#include "systemlogappender.h" diff --git a/ext/Log4Qt/deploy/include/TTCCLayout b/ext/Log4Qt/deploy/include/TTCCLayout new file mode 100644 index 0000000..43703e3 --- /dev/null +++ b/ext/Log4Qt/deploy/include/TTCCLayout @@ -0,0 +1 @@ +#include "ttcclayout.h" diff --git a/ext/Log4Qt/deploy/include/TelnetAppender b/ext/Log4Qt/deploy/include/TelnetAppender new file mode 100644 index 0000000..7334f57 --- /dev/null +++ b/ext/Log4Qt/deploy/include/TelnetAppender @@ -0,0 +1 @@ +#include "telnetappender.h" diff --git a/ext/Log4Qt/deploy/include/WriterAppender b/ext/Log4Qt/deploy/include/WriterAppender new file mode 100644 index 0000000..72d2e50 --- /dev/null +++ b/ext/Log4Qt/deploy/include/WriterAppender @@ -0,0 +1 @@ +#include "writerappender.h" diff --git a/ext/Log4Qt/project-config.cmake.in b/ext/Log4Qt/project-config.cmake.in new file mode 100644 index 0000000..a75271e --- /dev/null +++ b/ext/Log4Qt/project-config.cmake.in @@ -0,0 +1,11 @@ +get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +include(${SELF_DIR}/@PROJECT_NAME@-targets.cmake) + +string(TOUPPER @PROJECT_NAME@ PROJECT_TO_UPPER) + +add_definitions(-D${PROJECT_TO_UPPER}) +if (NOT @LOG4QT_BUILD_STATIC@) + add_definitions(-D${PROJECT_TO_UPPER}_IMPORTS) +endif() +set(${PROJECT_TO_UPPER}_INCLUDE_DIRS @TARGET_INCLUDE_DIR@) diff --git a/ext/Log4Qt/src/Log4Qt.pri b/ext/Log4Qt/src/Log4Qt.pri new file mode 100644 index 0000000..66b9757 --- /dev/null +++ b/ext/Log4Qt/src/Log4Qt.pri @@ -0,0 +1,108 @@ + +HEADERS += $$PWD/appender.h \ + $$PWD/appenderskeleton.h \ + $$PWD/basicconfigurator.h \ + $$PWD/colorconsoleappender.h \ + $$PWD/consoleappender.h \ + $$PWD/dailyrollingfileappender.h \ + $$PWD/asyncappender.h \ + $$PWD/mainthreadappender.h \ +# $$PWD/ databaseappender.h \ +# $$PWD/ databaselayout.h \ + $$PWD/fileappender.h \ + $$PWD/hierarchy.h \ + $$PWD/layout.h \ + $$PWD/level.h \ + $$PWD/log4qt.h \ + $$PWD/log4qtshared.h \ + $$PWD/logger.h \ + $$PWD/loggerrepository.h \ + $$PWD/loggingevent.h \ + $$PWD/logmanager.h \ + $$PWD/mdc.h \ + $$PWD/ndc.h \ + $$PWD/patternlayout.h \ + $$PWD/propertyconfigurator.h \ + $$PWD/rollingfileappender.h \ + $$PWD/signalappender.h \ + $$PWD/simplelayout.h \ + $$PWD/simpletimelayout.h \ + $$PWD/ttcclayout.h \ + $$PWD/telnetappender.h \ + $$PWD/writerappender.h \ + $$PWD/systemlogappender.h \ + $$PWD/helpers/classlogger.h \ + $$PWD//helpers/appenderattachable.h \ + $$PWD/helpers/configuratorhelper.h \ + $$PWD/helpers/datetime.h \ + $$PWD/helpers/factory.h \ + $$PWD/helpers/initialisationhelper.h \ + $$PWD/helpers/logerror.h \ + $$PWD/helpers/logobject.h \ + $$PWD/helpers/logobjectptr.h \ + $$PWD/helpers/optionconverter.h \ + $$PWD/helpers/patternformatter.h \ + $$PWD/helpers/properties.h \ + $$PWD/helpers/dispatcher.h \ + $$PWD/spi/filter.h \ + $$PWD/varia/debugappender.h \ + $$PWD/varia/denyallfilter.h \ + $$PWD/varia/levelmatchfilter.h \ + $$PWD/varia/levelrangefilter.h \ + $$PWD/varia/listappender.h \ + $$PWD/varia/nullappender.h \ + $$PWD/varia/stringmatchfilter.h \ + $$PWD/logstream.h + +SOURCES += $$PWD/appenderskeleton.cpp \ + $$PWD/basicconfigurator.cpp \ + $$PWD/colorconsoleappender.cpp \ + $$PWD/consoleappender.cpp \ + $$PWD/dailyrollingfileappender.cpp \ + $$PWD/asyncappender.cpp \ + $$PWD/mainthreadappender.cpp \ +# $$PWD/databaseappender.cpp \ +# $$PWD/databaselayout.cpp \ + $$PWD/fileappender.cpp \ + $$PWD/hierarchy.cpp \ + $$PWD/layout.cpp \ + $$PWD/level.cpp \ + $$PWD/log4qt.cpp \ + $$PWD/logger.cpp \ + $$PWD/loggerrepository.cpp \ + $$PWD/loggingevent.cpp \ + $$PWD/logmanager.cpp \ + $$PWD/mdc.cpp \ + $$PWD/ndc.cpp \ + $$PWD/patternlayout.cpp \ + $$PWD/propertyconfigurator.cpp \ + $$PWD/rollingfileappender.cpp \ + $$PWD/signalappender.cpp \ + $$PWD/simplelayout.cpp \ + $$PWD/simpletimelayout.cpp \ + $$PWD/ttcclayout.cpp \ + $$PWD/telnetappender.cpp \ + $$PWD/writerappender.cpp \ + $$PWD/systemlogappender.cpp \ + $$PWD/helpers/classlogger.cpp \ + $$PWD/helpers/appenderattachable.cpp \ + $$PWD/helpers/configuratorhelper.cpp \ + $$PWD/helpers/datetime.cpp \ + $$PWD/helpers/factory.cpp \ + $$PWD/helpers/initialisationhelper.cpp \ + $$PWD/helpers/logerror.cpp \ + $$PWD/helpers/logobject.cpp \ + $$PWD/helpers/logobjectptr.cpp \ + $$PWD/helpers/optionconverter.cpp \ + $$PWD/helpers/patternformatter.cpp \ + $$PWD/helpers/properties.cpp \ + $$PWD/helpers/dispatcher.cpp \ + $$PWD/spi/filter.cpp \ + $$PWD/varia/debugappender.cpp \ + $$PWD/varia/denyallfilter.cpp \ + $$PWD/varia/levelmatchfilter.cpp \ + $$PWD/varia/levelrangefilter.cpp \ + $$PWD/varia/listappender.cpp \ + $$PWD/varia/nullappender.cpp \ + $$PWD/varia/stringmatchfilter.cpp \ + $$PWD/logstream.cpp diff --git a/ext/Log4Qt/src/appender.h b/ext/Log4Qt/src/appender.h new file mode 100755 index 0000000..a87d19a --- /dev/null +++ b/ext/Log4Qt/src/appender.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * package: + * file: appender.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_APPENDER_H +#define LOG4QT_APPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "helpers/logobject.h" + +#include "helpers/logobjectptr.h" + +#include "logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class LoggingEvent; + + /*! + * \brief The class Appender is the base class for all Appenders. + * + * To allow the whole hirarchy to be an ascendant of QObject Appender is + * not an interface. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT Appender : public LogObject + { + Q_OBJECT + + /*! + * The property holds the Layout used by the Appender. + * + * \sa layout(), setLayout() + */ + Q_PROPERTY(Layout* layout READ layout WRITE setLayout) + + /*! + * The property holds the name of the Appender. + * + * \sa name(), setName() + */ + Q_PROPERTY(QString name READ name WRITE setName) + + /*! + * The property holds if the Appender requires a Layout or not. + * + * \sa requiresLayout(), setRequiresLayout() + */ + Q_PROPERTY(bool requiresLayout READ requiresLayout) + + public: + Appender(QObject *pParent = 0); + virtual ~Appender(); + private: + Appender(const Appender &rOther); // Not implemented + Appender &operator=(const Appender &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const = 0; + virtual QString name() const = 0; + virtual Layout *layout() const = 0; + virtual bool requiresLayout() const = 0; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout) = 0; + virtual void setName(const QString &rName) = 0; + + virtual void addFilter(Filter *pFilter) = 0; + virtual void clearFilters() = 0; + virtual void close() = 0; + virtual void doAppend(const LoggingEvent &rEvent) = 0; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Appender::Appender(QObject *pParent) : + LogObject(pParent) + {} + + inline Appender::~Appender() + {} + + +} // namespace Log4Qt + + +//Q_DECLARE_TYPEINFO(::Appender, Q_COMPLEX_TYPE); // Use default +//Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<Log4Qt::Appender>, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_APPENDER_H diff --git a/ext/Log4Qt/src/appenderskeleton.cpp b/ext/Log4Qt/src/appenderskeleton.cpp new file mode 100644 index 0000000..78be62c --- /dev/null +++ b/ext/Log4Qt/src/appenderskeleton.cpp @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * package: + * file: appenderskeleton.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 "appenderskeleton.h" + +#include <QtCore/QDebug> +#include "layout.h" +#include "loggingevent.h" +#include "logmanager.h" +#include "spi/filter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + ***************************************************************************/ + + + /*! + * \brief The class RecursionGuardLocker controls a boolean flag. + * + * It is a helper class to control a boolean flag. The class sets the flag + * on creation and resets it on destruction. + */ + class RecursionGuardLocker + { + public: + RecursionGuardLocker(bool *pGuard); + ~RecursionGuardLocker(); + private: + RecursionGuardLocker(const RecursionGuardLocker &rOther); // Not implemented + RecursionGuardLocker &operator=(const RecursionGuardLocker &rOther); // Not implemented + private: + bool *mpGuard; + }; + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: RecursionGuardLocker + ***************************************************************************/ + + + inline RecursionGuardLocker::RecursionGuardLocker(bool *pGuard) + { + Q_ASSERT_X(pGuard != 0, "RecursionGuardLocker::RecursionGuardLocker()", "Pointer to guard bool must not be null"); + + mpGuard = pGuard; + *mpGuard = true; + } + + + inline RecursionGuardLocker::~RecursionGuardLocker() + { + *mpGuard = false; + } + + + /************************************************************************** + * Class implementation: AppenderSkeleton + **************************************************************************/ + + + AppenderSkeleton::AppenderSkeleton(QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(true), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + AppenderSkeleton::AppenderSkeleton(const bool isActive, + QObject *pParent) : + Appender(pParent), + mObjectGuard(QMutex::Recursive), // Recursive for doAppend() + mAppendRecursionGuard(false), + mIsActive(isActive), + mIsClosed(false), + mpLayout(0), + mThreshold(Level::NULL_INT), + mpHeadFilter(0), + mpTailFilter(0) + { + } + + + void AppenderSkeleton::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of appender '%1' that requires layout and has no layout set"), + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return; + } + mIsActive = true; + } + + + void AppenderSkeleton::addFilter(Filter *pFilter) + { + if(!pFilter) + { + logger()->warn("Adding null Filter to Appender '%1'", name()); + return; + } + + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = pFilter; + if (mpHeadFilter) + mpHeadFilter->setNext(pFilter); + else + mpHeadFilter = pFilter; + } + + + void AppenderSkeleton::clearFilters() + { + QMutexLocker locker(&mObjectGuard); + + mpTailFilter = 0; + mpHeadFilter = 0; + } + + + void AppenderSkeleton::close() + { + QMutexLocker locker(&mObjectGuard); + + mIsClosed = true; + mIsActive = false; + } + + void AppenderSkeleton::customEvent(QEvent* event) + { + if (event->type() == LoggingEvent::eventId) { + LoggingEvent *logEvent = static_cast<LoggingEvent*>(event); + doAppend(*logEvent); + return ; + } + QObject::customEvent(event); + } + + void AppenderSkeleton::doAppend(const LoggingEvent &rEvent) + { + // The mutex serialises concurrent access from multiple threads. + // - e.g. two threads using the same logger + // - e.g. two threads using different logger with the same appender + // + // A call from the same thread will pass the mutex (QMutex::Recursive) + // and get to the recursion guard. The recursion guard blocks recursive + // invocation and prevents a possible endless loop. + // - e.g. an appender logs an error with a logger that uses it + + QMutexLocker locker(&mObjectGuard); + + if (mAppendRecursionGuard) + return; + + RecursionGuardLocker recursion_locker(&mAppendRecursionGuard); + + if (!checkEntryConditions()) + return; + if (!isAsSevereAsThreshold(rEvent.level())) + return; + + Filter *p_filter = mpHeadFilter; + while(p_filter) + { + Filter::Decision decision = p_filter->decide(rEvent); + if (decision == Filter::ACCEPT) + break; + else if (decision == Filter::DENY) + return; + else + p_filter = p_filter->next(); + } + + append(rEvent); + } + + + bool AppenderSkeleton::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!isActive()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of non activated appender '%1'"), + APPENDER_NOT_ACTIVATED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (isClosed()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of closed appender '%1'"), + APPENDER_CLOSED_ERROR); + e << name(); + logger()->error(e); + return false; + } + if (requiresLayout() && !layout()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' that requires layout and has no layout set"), + APPENDER_USE_MISSING_LAYOUT_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return true; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/appenderskeleton.h b/ext/Log4Qt/src/appenderskeleton.h new file mode 100644 index 0000000..f100a8f --- /dev/null +++ b/ext/Log4Qt/src/appenderskeleton.h @@ -0,0 +1,230 @@ +/****************************************************************************** + * + * package: + * file: appenderskeleton.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 _APPENDERSKELETON_H +#define _APPENDERSKELETON_H + + +/****************************************************************************** + * Dependencies +******************************************************************************/ + +#include "appender.h" +#include "log4qtshared.h" + +#include <QtCore/QMutex> +#include "helpers/logobjectptr.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Filter; + class Layout; + class Logger; + class LoggingEvent; + + /*! + * \brief The class AppenderSkeleton implements general Appender functionality. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT AppenderSkeleton : public Appender + { + Q_OBJECT + + /*! + * The property holds if the Appender has been activated. + * + * \sa isActive() + */ + Q_PROPERTY(bool isActive READ isActive) + + /*! + * The property holds if the Appender has been closed. + * + * \sa isClosed() + */ + Q_PROPERTY(bool isClosed READ isClosed) + + /*! + * The property holds the threshold level used by the Appender. + * + * \sa threshold(), setThreshold() + */ + Q_PROPERTY(Log4Qt::Level threshold READ threshold WRITE setThreshold) + + public: + AppenderSkeleton(QObject *pParent = 0); + + protected: + AppenderSkeleton(const bool isActive, + QObject *pParent = 0); + + public: + // virtual ~AppenderSkeleton(); Use compiler default + private: + AppenderSkeleton(const AppenderSkeleton &rOther); // Not implemented + AppenderSkeleton &operator=(const AppenderSkeleton &rOther); // Not implemented + + public: + // JAVA: ErrorHandler* errorHandler(); + virtual Filter *filter() const; + virtual Layout *layout() const; + bool isActive() const; + bool isClosed() const; + virtual QString name() const; + Level threshold() const; + // JAVA: void setErrorHandler(ErrorHandler *pErrorHandler); + virtual void setLayout(Layout *pLayout); + virtual void setName(const QString &rName); + void setThreshold(Level level); + + virtual void activateOptions(); + virtual void addFilter(Filter *pFilter); + virtual void clearFilters(); + virtual void close(); + + /*! + * Performs checks and delegates the actuall appending to the subclass + * specific append() function. + * + * \sa append(), checkEntryConditions(), isAsSevereAsThreshold(), Filter + */ + virtual void doAppend(const LoggingEvent &rEvent); + + // JAVA: void finalize(); + Filter* firstFilter() const; + bool isAsSevereAsThreshold(Level level) const; + + protected: + virtual void append(const LoggingEvent &rEvent) = 0; + void customEvent(QEvent* event); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. + * + * The checked conditions are: + * - That the appender has been activated (APPENDER_NOT_ACTIVATED_ERROR) + * - That the appender was not closed (APPENDER_CLOSED_ERROR) + * - That the appender has a layout set, if it requires one + * (logging_error(APPENDER_USE_MISSING_LAYOUT_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by doAppend(). The doAppend() function calls the subclass + * specific checkEntryConditions() function. The function checks the + * class specific conditions and calls checkEntryConditions() of + * it's parent class. The last function called is + * AppenderSkeleton::checkEntryConditions(). + * + * \sa doAppend() + */ + virtual bool checkEntryConditions() const; + + protected: + mutable QMutex mObjectGuard; + + private: + bool mAppendRecursionGuard; + volatile bool mIsActive; + volatile bool mIsClosed; + LogObjectPtr<Layout> mpLayout; + Level mThreshold; + LogObjectPtr<Filter> mpHeadFilter; + LogObjectPtr<Filter> mpTailFilter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter *AppenderSkeleton::filter() const + { QMutexLocker locker(&mObjectGuard); + return mpHeadFilter; } + + inline Layout *AppenderSkeleton::layout() const + { QMutexLocker locker(&mObjectGuard); + return mpLayout; } + + inline QString AppenderSkeleton::name() const + { QMutexLocker locker(&mObjectGuard); + return objectName(); } + + inline Level AppenderSkeleton::threshold() const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void AppenderSkeleton::setLayout(Layout *pLayout) + { QMutexLocker locker(&mObjectGuard); + mpLayout = pLayout; } + + inline void AppenderSkeleton::setName(const QString &rName) + { QMutexLocker locker(&mObjectGuard); + setObjectName(rName); } + + inline void AppenderSkeleton::setThreshold(Level level) + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool AppenderSkeleton::isActive() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsActive; } + + inline bool AppenderSkeleton::isClosed() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mIsClosed; } + + inline Filter *AppenderSkeleton::firstFilter() const + { QMutexLocker locker(&mObjectGuard); + return filter(); } + + inline bool AppenderSkeleton::isAsSevereAsThreshold(Level level) const + { // QMutexLocker locker(&mObjectGuard); // Level is threadsafe + return (mThreshold <= level); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(::AppenderSkeleton, Q_COMPLEX_TYPE); // Use default + + +#endif // _APPENDERSKELETON_H diff --git a/ext/Log4Qt/src/asyncappender.cpp b/ext/Log4Qt/src/asyncappender.cpp new file mode 100644 index 0000000..251f87f --- /dev/null +++ b/ext/Log4Qt/src/asyncappender.cpp @@ -0,0 +1,157 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: asyncappender.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. + * + ******************************************************************************/ + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "asyncappender.h" +#include "loggingevent.h" +#include "helpers/dispatcher.h" + +#include <QtCore/QDebug> +#include <QtCore/QCoreApplication> +#include <QtCore/QReadLocker> + +namespace Log4Qt +{ + +/************************************************************************** + * Declarations + **************************************************************************/ + + +/************************************************************************** + * C helper functions + **************************************************************************/ + + +/************************************************************************** + * Class implementation: AsyncAppender + **************************************************************************/ + + +AsyncAppender::AsyncAppender(QObject *parent) : AppenderSkeleton(parent) + ,mpThread(0) + ,mpDispatcher(0) +{ +} + +AsyncAppender::~AsyncAppender() +{ + close(); +} + +bool AsyncAppender::requiresLayout() const +{ + return false; +} + +void AsyncAppender::activateOptions() +{ + if (mpThread) + return; + + mpThread = new QThread(); + mpDispatcher = new Dispatcher(); + mpDispatcher->setAsyncAppender(this); + + mpDispatcher->moveToThread(mpThread); + mpThread->start(); +} + +void AsyncAppender::close() +{ + if (mpThread) + { + mpDispatcher->setAsyncAppender(0); + mpThread->quit(); + mpThread->wait(); + delete mpThread; + mpThread = 0; + delete mpDispatcher; + mpDispatcher = 0; + } +} + +void AsyncAppender::callAppenders(const LoggingEvent &rEvent) const +{ + QReadLocker locker(&mAppenderGuard); + + Appender *pAppender; + Q_FOREACH(pAppender, mAppenders) + pAppender->doAppend(rEvent); +} + +void AsyncAppender::append(const LoggingEvent &rEvent) +{ + // Post to the event loop of the dispatcher + LoggingEvent *event = new LoggingEvent(rEvent); + qApp->postEvent(mpDispatcher, event); +} + +bool AsyncAppender::checkEntryConditions() const +{ + if (mpThread && !mpThread->isRunning()) + { + LogError + e = + LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a running dispatcher thread"), + APPENDER_ASNC_DISPATCHER_NOT_RUNNING); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); +} + +#ifndef QT_NO_DEBUG_STREAM +/*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %AsyncAppender(name:"WA" ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ +QDebug AsyncAppender::debug(QDebug &rDebug) const +{ + rDebug.nospace() << "AsyncAppender(" + << "name:" << name() << " " + << ")"; + + return rDebug.space(); +} +#endif // QT_NO_DEBUG_STREAM + + +/************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + +} // namespace Log4Qt + diff --git a/ext/Log4Qt/src/asyncappender.h b/ext/Log4Qt/src/asyncappender.h new file mode 100644 index 0000000..d004e82 --- /dev/null +++ b/ext/Log4Qt/src/asyncappender.h @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: asyncappender.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 LOG4QT_ASYNCAPPENDER_H +#define LOG4QT_ASYNCAPPENDER_H + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" +#include "helpers/appenderattachable.h" + +#include <QtCore/QQueue> +#include <QtCore/QMutex> + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + +class Dispatcher; + +/*! + * \brief The class AsyncAppender lets users log events asynchronously. + * + * The AsyncAppender will collect the events sent to it and then dispatch them to all the + * appenders that are attached to it. You can attach multiple appenders to an AsyncAppender. + * + * The AsyncAppender uses a separate thread to serve the events fromthe event loop. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ +class LOG4QT_EXPORT AsyncAppender : public AppenderSkeleton, public AppenderAttachable +{ +Q_OBJECT + +public: + AsyncAppender(QObject *parent = 0); + virtual ~AsyncAppender(); + + virtual bool requiresLayout() const; + + virtual void activateOptions(); + virtual void close(); + void callAppenders(const LoggingEvent &rEvent) const; + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - dispatcher thread running (APPENDER_ASNC_DISPATCHER_NOT_RUNNING) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + +protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %AsyncAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + +private: + Q_DISABLE_COPY(AsyncAppender) + + //! Event dispatcher trhead + QThread *mpThread; + Dispatcher *mpDispatcher; +}; + + +/************************************************************************** + * Operators, Helper + **************************************************************************/ + + +/************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::AsyncAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_AsyncAppender_H diff --git a/ext/Log4Qt/src/basicconfigurator.cpp b/ext/Log4Qt/src/basicconfigurator.cpp new file mode 100755 index 0000000..d6998c6 --- /dev/null +++ b/ext/Log4Qt/src/basicconfigurator.cpp @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * package: + * file: basicconfigurator.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 "basicconfigurator.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDebug> +#include <QtCore/QThread> +#include "consoleappender.h" +#include "helpers/configuratorhelper.h" +#include "helpers/logobjectptr.h" +#include "logmanager.h" +#include "patternlayout.h" +#include "varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: BasicConfigurator + **************************************************************************/ + + + bool BasicConfigurator::configure() + { + LogObjectPtr<ListAppender> list = new ListAppender; + list->setName(QLatin1String("BasicConfigurator")); + list->setConfiguratorList(true); + list->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(list); + + PatternLayout *p_layout = new PatternLayout(PatternLayout::TTCC_CONVERSION_PATTERN); + p_layout->setName(QLatin1String("BasicConfigurator TTCC")); + p_layout->activateOptions(); + ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_appender->setName(QLatin1String("BasicConfigurator stdout")); + p_appender->activateOptions(); + LogManager::rootLogger()->addAppender(p_appender); + + LogManager::logLogger()->removeAppender(list); + ConfiguratorHelper::setConfigureError(list->list()); + return (list->list().count() == 0); + } + + + void BasicConfigurator::configure(Appender *pAppender) + { + LogManager::rootLogger()->addAppender(pAppender); + } + + + void BasicConfigurator::resetConfiguration() + { + LogManager::resetConfiguration(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/basicconfigurator.h b/ext/Log4Qt/src/basicconfigurator.h new file mode 100755 index 0000000..6189cc0 --- /dev/null +++ b/ext/Log4Qt/src/basicconfigurator.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * + * package: + * file: basicconfigurator.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_BASICCONFIGURATOR_H +#define LOG4QT_BASICCONFIGURATOR_H + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include <QtCore/Qt> +#include "log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Appender; + + /*! + * \brief The class BasicConfigurator provides a simple package + * configuration. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT BasicConfigurator + { + private: + BasicConfigurator(); // Not implemented + // BasicConfigurator(const BasicConfigurator &rOther); // Use compiler default + // virtual ~BasicConfigurator(); // Use compiler default + // BasicConfigurator &operator=(const BasicConfigurator &rOther); // Use compiler default + + public: + static bool configure(); + static void configure(Appender *pAppender); + static void resetConfiguration(); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namspace + + +// Q_DECLARE_TYPEINFO(::BasicConfigurator, Q_MOVABLE_TYPE); // Use default + + +#endif // _BASICCONFIGURATOR_H diff --git a/ext/Log4Qt/src/colorconsoleappender.cpp b/ext/Log4Qt/src/colorconsoleappender.cpp new file mode 100644 index 0000000..e83fafd --- /dev/null +++ b/ext/Log4Qt/src/colorconsoleappender.cpp @@ -0,0 +1,290 @@ +/****************************************************************************** + * + * package: log4qt + * file: colorconsoleappender.cpp + * created: March 2010 + * author: Filonenko Michael + * + * + * Copyright 2010 Filonenko Michael + * + * 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 "colorconsoleappender.h" + +#include <QtCore/QTextStream> + +#include "loggingevent.h" +#include "layout.h" + +#define NIX_BACK_BLACK 40 +#define NIX_BACK_RED 41 +#define NIX_BACK_GREEN 42 +#define NIX_BACK_YELLOW 43 +#define NIX_BACK_BLUE 44 +#define NIX_BACK_MAGNETTA 45 +#define NIX_BACK_CYAN 46 +#define NIX_BACK_GRAY 47 + +#define NIX_FORE_BLACK 30 +#define NIX_FORE_RED 31 +#define NIX_FORE_GREEN 32 +#define NIX_FORE_YELLOW 33 +#define NIX_FORE_BLUE 34 +#define NIX_FORE_MAGNETTA 35 +#define NIX_FORE_CYAN 36 +#define NIX_FORE_GRAY 37 + +#define NIX_FORE_BOLD 1 + +#define NIX_DEFAULT 0 + +#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) +//#include <windows.h> +#define WIN_BACK_BLACK 0 +#define WIN_BACK_RED BACKGROUND_RED +#define WIN_BACK_LIGHT_RED BACKGROUND_RED | BACKGROUND_INTENSITY +#define WIN_BACK_GREEN BACKGROUND_GREEN +#define WIN_BACK_LIGHT_GREEN BACKGROUND_GREEN | BACKGROUND_INTENSITY +#define WIN_BACK_YELLOW BACKGROUND_GREEN | BACKGROUND_RED +#define WIN_BACK_LIGHT_YELLOW BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY +#define WIN_BACK_BLUE BACKGROUND_BLUE +#define WIN_BACK_LIGHT_BLUE BACKGROUND_BLUE | BACKGROUND_INTENSITY +#define WIN_BACK_MAGNETTA BACKGROUND_RED | BACKGROUND_BLUE +#define WIN_BACK_LIGHT_MAGNETTA BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY +#define WIN_BACK_CYAN BACKGROUND_BLUE | BACKGROUND_GREEN +#define WIN_BACK_LIGHT_CYAN BACKGROUND_BLUE | BACKGROUND_GREEN +#define WIN_BACK_GRAY BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED +#define WIN_BACK_WHITE BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY + +#define WIN_FORE_BLACK 0 +#define WIN_FORE_RED FOREGROUND_RED +#define WIN_FORE_LIGHT_RED FOREGROUND_RED | FOREGROUND_INTENSITY +#define WIN_FORE_GREEN FOREGROUND_GREEN +#define WIN_FORE_LIGHT_GREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY +#define WIN_FORE_YELLOW FOREGROUND_GREEN | FOREGROUND_RED +#define WIN_FORE_LIGHT_YELLOW FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY +#define WIN_FORE_BLUE FOREGROUND_BLUE +#define WIN_FORE_LIGHT_BLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY +#define WIN_FORE_MAGNETTA FOREGROUND_RED | FOREGROUND_BLUE +#define WIN_FORE_LIGHT_MAGNETTA FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY +#define WIN_FORE_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN +#define WIN_FORE_LIGHT_CYAN FOREGROUND_BLUE | FOREGROUND_GREEN +#define WIN_FORE_GRAY FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED +#define WIN_FORE_WHITE FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY + +#define WIN_FORE_BOLD FOREGROUND_INTENSITY + +#define WIN_DEFAULT FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED + +static void colorOutputString(HANDLE hConsole, const QString& output) +{ + QString message = output; + + // save colors + CONSOLE_SCREEN_BUFFER_INFO cbi; + GetConsoleScreenBufferInfo(hConsole,&cbi); + + wchar_t *wideMessage; + + QStringList colorizedMessage = message.split('\033'); + + int actualSize; + DWORD out; + + WORD color = 0; + WORD newColor = 0; + QString parsedWordString; + QStringList escParams; + int indexOfM; + // display first part of message + if (!colorizedMessage.at(0).isEmpty()) { + wideMessage = new wchar_t [colorizedMessage.at(0).size()]; + actualSize = colorizedMessage.at(0).toWCharArray(wideMessage); + WriteConsoleW(hConsole, wideMessage, actualSize, &out, 0); + delete [] wideMessage; + colorizedMessage.removeAt(0); + } + foreach (QString it, colorizedMessage) { + // color setted + if (it.startsWith("[")) { + indexOfM = it.indexOf('m'); + // not esc-sequence + if (indexOfM != -1) { + parsedWordString = it.mid(1, indexOfM - 1); + + escParams = parsedWordString.split(';'); + foreach(QString param, escParams) { + color = param.toUInt(); + switch(color) { + case NIX_DEFAULT: + newColor = WIN_DEFAULT; + break; + case NIX_FORE_BOLD: + newColor |= WIN_FORE_BOLD; + break; + case NIX_BACK_BLACK : + newColor = (newColor & 0x0f) | WIN_BACK_BLACK; + break; + case NIX_BACK_RED : + newColor = (newColor & 0x0f) | WIN_BACK_RED; + break; + case NIX_BACK_GREEN : + newColor = (newColor & 0x0f) | WIN_BACK_GREEN; + break; + case NIX_BACK_YELLOW : + newColor = (newColor & 0x0f) | WIN_BACK_YELLOW; + break; + case NIX_BACK_BLUE : + newColor = (newColor & 0x0f) | WIN_BACK_BLUE; + break; + case NIX_BACK_MAGNETTA : + newColor = (newColor & 0x0f) | WIN_BACK_MAGNETTA; + break; + case NIX_BACK_CYAN : + newColor = (newColor & 0x0f) | WIN_BACK_CYAN; + break; + case NIX_BACK_GRAY : + newColor = (newColor & 0x0f) | WIN_BACK_GRAY; + break; + case NIX_FORE_BLACK : + newColor = (newColor & 0xF8)| WIN_FORE_BLACK; + break; + case NIX_FORE_RED : + newColor = (newColor & 0xF8) | WIN_FORE_RED; + break; + case NIX_FORE_GREEN : + newColor = (newColor & 0xF8) | WIN_FORE_GREEN; + break; + case NIX_FORE_YELLOW : + newColor = (newColor & 0xF8) | WIN_FORE_YELLOW; + break; + case NIX_FORE_BLUE : + newColor = (newColor & 0xF8) | WIN_FORE_BLUE; + break; + case NIX_FORE_MAGNETTA : + newColor = (newColor & 0xF8) | WIN_FORE_MAGNETTA; + break; + case NIX_FORE_CYAN : + newColor = (newColor & 0xF8) | WIN_FORE_CYAN; + break; + case NIX_FORE_GRAY : + newColor = (newColor & 0xF8) | WIN_FORE_GRAY; + break; + default:break; + } + } + it = it.mid(indexOfM + 1); + + SetConsoleTextAttribute(hConsole, newColor); + } + } + + wideMessage = new wchar_t [it.size()]; + actualSize = it.toWCharArray(wideMessage); + WriteConsoleW(hConsole, wideMessage, actualSize, &out, 0); + delete [] wideMessage; + } + // load old colors + SetConsoleTextAttribute(hConsole, cbi.wAttributes); + + //qDebug() << colorizedMessage; + +} +#endif + +namespace Log4Qt { + + /************************************************************************** + * Declarations + **************************************************************************/ + + /************************************************************************** + * C helper functions + **************************************************************************/ + + /************************************************************************** + * Class implementation: ColorConsoleAppender + **************************************************************************/ + + ColorConsoleAppender::ColorConsoleAppender(QObject *pParent) : + ConsoleAppender(pParent) + { + } + + ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, QObject *pParent) : + ConsoleAppender(pLayout, pParent) + { + } + + ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, + const QString &rTarget, QObject *pParent) : + ConsoleAppender(pLayout, rTarget, pParent) + { + } + + ColorConsoleAppender::ColorConsoleAppender(Layout *pLayout, Target target, + QObject *pParent) : + ConsoleAppender(pLayout, target, pParent) + { + } + +#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) +void ColorConsoleAppender::append(const LoggingEvent &rEvent) +{ + QString message = layout()->format(rEvent); + + colorOutputString(hConsole, message); + + // обрабатываем ошибки, по умолчанию метод не реализован + if (handleIoErrors()) + return; + + if (immediateFlush()) + { + writer()->flush(); + if (handleIoErrors()) + return; + } +} + +void ColorConsoleAppender::activateOptions() +{ + ConsoleAppender::activateOptions(); + + if (target() == "STDOUT_TARGET") + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + else + hConsole = GetStdHandle(STD_ERROR_HANDLE); +} + +void ColorConsoleAppender::close() +{ + ConsoleAppender::close(); + CloseHandle(hConsole); +} + +#endif + +/****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + +} // namespace Log4Qt + diff --git a/ext/Log4Qt/src/colorconsoleappender.h b/ext/Log4Qt/src/colorconsoleappender.h new file mode 100755 index 0000000..5027b5d --- /dev/null +++ b/ext/Log4Qt/src/colorconsoleappender.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * package: log4qt + * file: colorconsoleappender.h + * created: March 2010 + * author: Filonenko Michael + * + * + * Copyright 2010 Filonenko Michael + * + * 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 _COLORCONSOLEAPPENDER_H +#define _COLORCONSOLEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "consoleappender.h" + +#include <QtCore/QHash> +#include <QtCore/QPair> +#include <QtCore/QRegExp> + +// if we are in WIN* +#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#include <windows.h> +#endif + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class ColorConsoleAppender appends to stdout or stderr with color formatting. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT ColorConsoleAppender : public ConsoleAppender + { + Q_OBJECT + + public: + + ColorConsoleAppender(QObject *pParent = 0); + ColorConsoleAppender(Layout *pLayout, + QObject *pParent = 0); + ColorConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent = 0); + + /*! + * Creates a ConsoleAppender with the layout \a pLayout, the target + * value specified by the \a target constant and the parent + * \a pParent. + */ + ColorConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent = 0); + // if we are in WIN* + #if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) + + virtual void activateOptions(); + + virtual void close(); +protected: + virtual void append(const LoggingEvent& rEvent); + private: + HANDLE hConsole; + #endif + + }; + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + +} // namespace Log4Qt + + +#endif // #ifndef _COLORCONSOLEAPPENDER_H diff --git a/ext/Log4Qt/src/consoleappender.cpp b/ext/Log4Qt/src/consoleappender.cpp new file mode 100755 index 0000000..c33159e --- /dev/null +++ b/ext/Log4Qt/src/consoleappender.cpp @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * package: + * file: consoleappender.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 "consoleappender.h" + +#include <QtCore/QDebug> +#include <QtCore/QTextStream> +#include "helpers/optionconverter.h" +#include "layout.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ConsoleAppender + **************************************************************************/ + + + ConsoleAppender::ConsoleAppender(QObject *pParent) : + WriterAppender(pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(STDOUT_TARGET), + mpTextStream(0) + { + setTarget(rTarget); + } + + + ConsoleAppender::ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mTarget(target), + mpTextStream(0) + { + } + + + ConsoleAppender::~ConsoleAppender() + { + close(); + + } + + + QString ConsoleAppender::target() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + if (mTarget == STDOUT_TARGET) + return QLatin1String("STDOUT_TARGET"); + else + return QLatin1String("STDERR_TARGET"); + } + + + void ConsoleAppender::setTarget(const QString &rTarget) + { + bool ok; + Target target = static_cast<Target>(OptionConverter::toTarget(rTarget, &ok)); + if (ok) + setTarget(target); + } + + + void ConsoleAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + closeStream(); + + if (mTarget == STDOUT_TARGET) + mpTextStream = new QTextStream(stdout); + else + mpTextStream = new QTextStream(stderr); + setWriter(mpTextStream); + + WriterAppender::activateOptions(); + } + + + void ConsoleAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeStream(); + } + + + void ConsoleAppender::closeStream() + { + // Q_ASSERT_X(, "ConsoleAppender::closeStream()", "Lock must be held by caller") + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ConsoleAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString target; + if (mTarget == STDOUT_TARGET) + target = QLatin1String("STDOUT"); + else + target = QLatin1String("STDERR"); + + rDebug.nospace() << "ConsoleAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "target:" << target << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/consoleappender.h b/ext/Log4Qt/src/consoleappender.h new file mode 100755 index 0000000..c2b3f9c --- /dev/null +++ b/ext/Log4Qt/src/consoleappender.h @@ -0,0 +1,160 @@ +/****************************************************************************** + * + * package: + * file: consoleappender.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 _CONSOLEAPPENDER_H +#define _CONSOLEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class ConsoleAppender appends to stdout or stderr. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT ConsoleAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds the target used by the appender. + * + * The default is STDOUT_TARGET for the standard output. + * + * \sa Target, target(), setTarget() + */ + Q_PROPERTY(QString target READ target WRITE setTarget) + + public: + /*! + * The enum defines the possible output targets + * + * \sa target(), setTarget() + */ + enum Target { + /*! The output target is standard out. */ + STDOUT_TARGET, + /*! The output target is standard error. */ + STDERR_TARGET + }; + Q_ENUMS(Target) + + ConsoleAppender(QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + QObject *pParent = 0); + ConsoleAppender(Layout *pLayout, + const QString &rTarget, + QObject *pParent = 0); + + /*! + * Creates a ConsoleAppender with the layout \a pLayout, the target + * value specified by the \a target constant and the parent + * \a pParent. + */ + ConsoleAppender(Layout *pLayout, + Target target, + QObject *pParent = 0); + + virtual ~ConsoleAppender(); + private: + ConsoleAppender(const ConsoleAppender &rOther); // Not implemented + ConsoleAppender &operator=(const ConsoleAppender &rOther); // Not implemented + + public: + // JAVA: bool follow() const; + QString target() const; + // JAVA: void setFollow(bool follow); + void setTarget(const QString &rTarget); + + /*! + * Sets the target to the value specified by the \a target constant. + */ + void setTarget(Target target); + + virtual void activateOptions(); + virtual void close(); + + protected: + void closeStream(); + + #ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %ConsoleAppender(name:"CA" filter:0x0 isactive:true isclosed:false + * layout:"PL" target:"STDERR" referenceCount:1 + * threshold:"WARN_SET") + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + #endif // QT_NO_DEBUG_STREAM + + private: + volatile Target mTarget; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline void ConsoleAppender::setTarget(Target target) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mTarget = target; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(::ConsoleAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // _CONSOLEAPPENDER_H diff --git a/ext/Log4Qt/src/dailyrollingfileappender.cpp b/ext/Log4Qt/src/dailyrollingfileappender.cpp new file mode 100755 index 0000000..a385d10 --- /dev/null +++ b/ext/Log4Qt/src/dailyrollingfileappender.cpp @@ -0,0 +1,352 @@ +/****************************************************************************** + * + * package: + * file: dailyrollingfileappender.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 "dailyrollingfileappender.h" + +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QMetaEnum> +#include <QtCore/QTextCodec> +#include "helpers/datetime.h" +#include "layout.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DailyRollingFileAppender + **************************************************************************/ + + + DailyRollingFileAppender::DailyRollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mDatePattern() + { + setDatePattern(DAILY_ROLLOVER); + } + + + DailyRollingFileAppender::DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mDatePattern() + { + setDatePattern(rDatePattern); + } + + + DailyRollingFileAppender::~DailyRollingFileAppender() + { + close(); + } + + + void DailyRollingFileAppender::setDatePattern(DatePattern datePattern) + { + switch (datePattern) + { + case MINUTELY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh-mm")); + break; + case HOURLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-hh")); + break; + case HALFDAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd-a")); + break; + case DAILY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM-dd")); + break; + case WEEKLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-ww")); + break; + case MONTHLY_ROLLOVER: + setDatePattern(QLatin1String("'.'yyyy-MM")); + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::setDatePattern()", "Invalid datePattern constant"); + setDatePattern(DAILY_ROLLOVER); + }; + } + + + void DailyRollingFileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + computeFrequency(); + if (!mActiveDatePattern.isEmpty()) + { + computeRollOverTime(); + FileAppender::activateOptions(); + } + } + + + void DailyRollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DailyRollingFileAppender::append()", "Lock must be held by caller") + + if (QDateTime::currentDateTime() > mRollOverTime) + rollOver(); + FileAppender::append(rEvent); + } + + + bool DailyRollingFileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "DailyRollingFileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (mActiveDatePattern.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without having a valid date pattern set"), + APPENDER_USE_INVALID_PATTERN_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return FileAppender::checkEntryConditions(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DailyRollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "DailyRollingFileAppender(" + << "name:" << name() << " " + << "activedatepattern:" << mActiveDatePattern << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "datepattern:" << datePattern() << " " + << "encoding:" << codec_name << " " + << "frequency:" << frequencyToString() << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "rollovertime:" << mRollOverTime + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void DailyRollingFileAppender::computeFrequency() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeFrequency()", "Lock must be held by caller") + + const DateTime start_time(QDate(1999, 1, 1), QTime(0, 0)); + const QString start_string = start_time.toString(mDatePattern); + mActiveDatePattern.clear(); + + if (start_string != static_cast<DateTime>(start_time.addSecs(60)).toString(mDatePattern)) + mFrequency = MINUTELY_ROLLOVER; + else if (start_string != static_cast<DateTime>(start_time.addSecs(60 * 60)).toString(mDatePattern)) + mFrequency = HOURLY_ROLLOVER; + else if (start_string != static_cast<DateTime>(start_time.addSecs(60 * 60 * 12)).toString(mDatePattern)) + mFrequency = HALFDAILY_ROLLOVER; + else if (start_string != static_cast<DateTime>(start_time.addDays(1)).toString(mDatePattern)) + mFrequency = DAILY_ROLLOVER; + else if (start_string != static_cast<DateTime>(start_time.addDays(7)).toString(mDatePattern)) + mFrequency = WEEKLY_ROLLOVER; + else if (start_string != static_cast<DateTime>(start_time.addMonths(1)).toString(mDatePattern)) + mFrequency = MONTHLY_ROLLOVER; + else + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("The pattern '%1' does not specify a frequency for appender '%2'"), + APPENDER_INVALID_PATTERN_ERROR); + e << mDatePattern << name(); + logger()->error(e); + return; + } + + mActiveDatePattern = mDatePattern; + logger()->trace("Frequency set to %2 using date pattern %1", + mActiveDatePattern, + frequencyToString()); + } + + + void DailyRollingFileAppender::computeRollOverTime() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::computeRollOverTime()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::computeRollOverTime()", "No active date pattern"); + + QDateTime now = QDateTime::currentDateTime(); + QDate now_date = now.date(); + QTime now_time = now.time(); + QDateTime start; + + switch (mFrequency) + { + case MINUTELY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + now_time.minute(), + 0, 0)); + mRollOverTime = start.addSecs(60); + } + break; + case HOURLY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(now_time.hour(), + 0, 0, 0)); + mRollOverTime = start.addSecs(60*60); + } + break; + case HALFDAILY_ROLLOVER: + { + int hour = now_time.hour(); + if (hour >= 12) + hour = 12; + else + hour = 0; + start = QDateTime(now_date, + QTime(hour, 0, 0, 0)); + mRollOverTime = start.addSecs(60*60*12); + } + break; + case DAILY_ROLLOVER: + { + start = QDateTime(now_date, + QTime(0, 0, 0, 0)); + mRollOverTime = start.addDays(1); + } + break; + case WEEKLY_ROLLOVER: + { + // QT numbers the week days 1..7. The week starts on Monday. + // Change it to being numbered 0..6, starting with Sunday. + int day = now_date.dayOfWeek(); + if (day == Qt::Sunday) + day = 0; + start = QDateTime(now_date, + QTime(0, 0, 0, 0)).addDays(-1 * day); + mRollOverTime = start.addDays(7); + } + break; + case MONTHLY_ROLLOVER: + { + start = QDateTime(QDate(now_date.year(), + now_date.month(), + 1), + QTime(0, 0, 0, 0)); + mRollOverTime = start.addMonths(1); + } + break; + default: + Q_ASSERT_X(false, "DailyRollingFileAppender::computeInterval()", "Invalid datePattern constant"); + mRollOverTime = QDateTime::fromTime_t(0); + } + + mRollOverSuffix = static_cast<DateTime>(start).toString(mActiveDatePattern); + Q_ASSERT_X(static_cast<DateTime>(now).toString(mActiveDatePattern) == mRollOverSuffix, + "DailyRollingFileAppender::computeRollOverTime()", "File name changes within interval"); + Q_ASSERT_X(mRollOverSuffix != static_cast<DateTime>(mRollOverTime).toString(mActiveDatePattern), + "DailyRollingFileAppender::computeRollOverTime()", "File name does not change with rollover"); + + logger()->trace("Computing roll over time from %1: The interval start time is %2. The roll over time is %3", + now, + start, + mRollOverTime); + } + + + QString DailyRollingFileAppender::frequencyToString() const + { + QMetaEnum meta_enum = metaObject()->enumerator(metaObject()->indexOfEnumerator("DatePattern")); + return QLatin1String(meta_enum.valueToKey(mFrequency)); + } + + + void DailyRollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "DailyRollingFileAppender::rollOver()", "Lock must be held by caller") + Q_ASSERT_X(!mActiveDatePattern.isEmpty(), "DailyRollingFileAppender::rollOver()", "No active date pattern"); + + QString roll_over_suffix = mRollOverSuffix; + computeRollOverTime(); + if (roll_over_suffix == mRollOverSuffix) + return; + + closeFile(); + + QString target_file_name = file() + roll_over_suffix; + QFile f(target_file_name); + if (f.exists() && !removeFile(f)) + return; + f.setFileName(file()); + if (!renameFile(f, target_file_name)) + return; + openFile(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/dailyrollingfileappender.h b/ext/Log4Qt/src/dailyrollingfileappender.h new file mode 100755 index 0000000..f01658b --- /dev/null +++ b/ext/Log4Qt/src/dailyrollingfileappender.h @@ -0,0 +1,196 @@ +/****************************************************************************** + * + * package: + * file: dailyrollingfileappender.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 _DAILYROLLINGFILEAPPENDER_H +#define _DAILYROLLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "fileappender.h" + +#include <QtCore/QDateTime> + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DailyRollingFileAppender extends FileAppender so that the + * underlying file is rolled over at a specified frequency. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT DailyRollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the date pattern used by the appender. + * + * The default is DAILY_ROLLOVER for rollover at midnight each day. + * + * \sa datePattern(), setDatePattern() + */ + Q_PROPERTY(QString datePattern READ datePattern WRITE setDatePattern) + + public: + /*! + * The enum DatePattern defines constants for date patterns. + * + * \sa setDatePattern(DatePattern) + */ + enum DatePattern + { + /*! The minutely date pattern string is "'.'yyyy-MM-dd-hh-mm". */ + MINUTELY_ROLLOVER = 0, + /*! The hourly date pattern string is "'.'yyyy-MM-dd-hh". */ + HOURLY_ROLLOVER, + /*! The half-daily date pattern string is "'.'yyyy-MM-dd-a". */ + HALFDAILY_ROLLOVER, + /*! The daily date pattern string is "'.'yyyy-MM-dd". */ + DAILY_ROLLOVER, + /*! The weekly date pattern string is "'.'yyyy-ww". */ + WEEKLY_ROLLOVER, + /*! The monthly date pattern string is "'.'yyyy-MM". */ + MONTHLY_ROLLOVER + }; + Q_ENUMS(DatePattern) + + DailyRollingFileAppender(QObject *pParent = 0); + DailyRollingFileAppender(Layout *pLayout, + const QString &rFileName, + const QString &rDatePattern, + QObject *pParent = 0); + virtual ~DailyRollingFileAppender(); + private: + DailyRollingFileAppender(const DailyRollingFileAppender &rOther); // Not implemented + DailyRollingFileAppender &operator=(const DailyRollingFileAppender &rOther); // Not implemented + + public: + QString datePattern() const; + + /*! + * Sets the datePattern to the value specified by the \a datePattern + * constant. + */ + void setDatePattern(DatePattern datePattern); + + void setDatePattern(const QString &rDatePattern); + + virtual void activateOptions(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * FileAppender::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A valid pattern has been set (APPENDER_USE_INVALID_PATTERN_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %DailyRollingFileAppender(name:"DRFA" activedatepattern:"'.'yyyy-MM-dd-hh-mm" + * appendfile:false bufferedio:true + * datepattern:"'.'yyyy-MM-dd-hh-mm" + * encoding:"" frequency:"MINUTELY_ROLLOVER" + * file:"log.txt" filter:0x0 immediateflush:true + * isactive:true isclosed:false layout:"TTCC" + * referencecount:1 + * rollovertime:QDateTime("Mon Oct 22 05:23:00 2007") + * threshold: "NULL" writer: 0x0 ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void computeFrequency(); + void computeRollOverTime(); + QString frequencyToString() const; + void rollOver(); + + private: + QString mDatePattern; + DatePattern mFrequency; + QString mActiveDatePattern; + QDateTime mRollOverTime; + QString mRollOverSuffix; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString DailyRollingFileAppender::datePattern() const + { QMutexLocker locker(&mObjectGuard); + return mDatePattern; } + + inline void DailyRollingFileAppender::setDatePattern(const QString &rDatePattern) + { QMutexLocker locker(&mObjectGuard); + mDatePattern = rDatePattern; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(::DailyRollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // _DAILYROLLINGFILEAPPENDER_H diff --git a/ext/Log4Qt/src/databaseappender.cpp b/ext/Log4Qt/src/databaseappender.cpp new file mode 100755 index 0000000..7b1900d --- /dev/null +++ b/ext/Log4Qt/src/databaseappender.cpp @@ -0,0 +1,224 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: databaseappender.cpp + * created: Marth 2010 + * author: Michael Filonenko + * + * + * Copyright 2010 Michael Filonenko + * + * 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 "databaseappender.h" + +#include <QtCore/QDebug> + +#include <QtSql/QSqlDriver> +#include <QtSql/QSqlQuery> +#include <QtSql/QSqlRecord> +#include <QtSql/QSqlField> +#include <QtSql/QSqlError> + + +#include "databaselayout.h" +#include "loggingevent.h" + +#include "helpers/datetime.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DatabaseAppender + **************************************************************************/ + + + DatabaseAppender::DatabaseAppender(QObject *pParent) : + AppenderSkeleton(false, pParent) + , connectionName(QSqlDatabase::defaultConnection) + , tableName(QString::null) + { + } + + + DatabaseAppender::DatabaseAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(false, pParent) + , connectionName(QSqlDatabase::defaultConnection) + , tableName(QString::null) + { + setLayout(pLayout); + } + + + DatabaseAppender::DatabaseAppender(Layout *pLayout + ,const QString& tableName + ,const QString& connection + ,QObject *pParent) : + AppenderSkeleton(false, pParent) + , connectionName(connection) + , tableName(tableName) + { + setLayout(pLayout); + } + + + DatabaseAppender::~DatabaseAppender() + { + close(); + } + + + void DatabaseAppender::setConnection(const QString& connection) + { + QMutexLocker locker(&mObjectGuard); + + if (connectionName == connection) + return; + + connectionName = connection; + } + + + void DatabaseAppender::setTable(const QString& table) + { + QMutexLocker locker(&mObjectGuard); + + if (table == tableName) + return; + + tableName = table; + } + + + void DatabaseAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (!QSqlDatabase::contains(connectionName) || tableName.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires sql connection and table and has no connection or table set") + , APPENDER_MISSING_DATABASE_OR_TABLE_ERROR); + e << name(); + logger()->error(e); + return; + } + + AppenderSkeleton::activateOptions(); + } + + + + bool DatabaseAppender::requiresLayout() const + { + return true; + } + + + void DatabaseAppender::append(const LoggingEvent &rEvent) + { + DatabaseLayout *databaseLayout = qobject_cast<DatabaseLayout *>(layout()); + + if (databaseLayout) { + QSqlRecord record = databaseLayout->formatRecord(rEvent); + + QSqlDatabase database = QSqlDatabase::database(connectionName); + QSqlQuery query(database); + if (!query.exec(database.driver()->sqlStatement(QSqlDriver::InsertStatement + , tableName, record, false))) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Sql query exec error: '%1'"), + APPENDER_EXEC_SQL_QUERY_ERROR, + Q_FUNC_INFO); + e << query.lastQuery() + " " + query.lastError().text(); + logger()->error(e); + } + } else { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' with invalid layout"), + APPENDER_INVALID_DATABASE_LAYOUT_ERROR); + e << name(); + logger()->error(e); + } + } + + + bool DatabaseAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "DatabaseAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!QSqlDatabase::contains(connectionName) || tableName.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' with invalid database or empty table name"), + APPENDER_MISSING_DATABASE_OR_TABLE_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DatabaseAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "DatabaseAppender(" + << "name:" << name() << " " + << "connection:" << connectionName << " " + << "table:" << tableName + << "filter:" << firstFilter() + << "isactive:" << isActive() + << "isclosed:" << isClosed() + << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/databaseappender.h b/ext/Log4Qt/src/databaseappender.h new file mode 100755 index 0000000..815fb2b --- /dev/null +++ b/ext/Log4Qt/src/databaseappender.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: databaseappender.h + * created: Marth 2010 + * author: Michael Filonenko + * + * + * Copyright 2010 Michael Filonenko + * + * 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 _DATABASEAPPENDER_H +#define _DATABASEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" + +#include <QtSql/QSqlDatabase> + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DatabaseAppender appends log events to a sql database. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT DatabaseAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds sql database connection the appender uses. + * + * The default is null to use the codec the writer has set. + * + * \sa connection(), setConnection() + */ + Q_PROPERTY(QString connection READ connection WRITE setConnection) + + /*! + * The property holds sql database table name + * + \sa table(), setTable() + */ + Q_PROPERTY(QString table READ table WRITE setTable) + public: + DatabaseAppender(QObject *pParent = 0); + DatabaseAppender(Layout *pLayout, + QObject *pParent = 0); + DatabaseAppender(Layout *pLayout + ,const QString& tableName + ,const QString& connection = QSqlDatabase::defaultConnection + ,QObject *pParent = 0); + virtual ~DatabaseAppender(); + + private: + DatabaseAppender(const DatabaseAppender &rOther); // Not implemented + DatabaseAppender &operator=(const DatabaseAppender &rOther); // Not implemented + + public: + virtual bool requiresLayout() const; + + QString connection() const; + QString table() const; + + void setConnection(const QString& connection); + void setTable(const QString& table); + + virtual void activateOptions(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeWriter(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %WriterAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + private: + QString connectionName; + QString tableName; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString DatabaseAppender::connection() const + { QMutexLocker locker(&mObjectGuard); + return connectionName; } + + inline QString DatabaseAppender::table() const + { QMutexLocker locker(&mObjectGuard); + return tableName; } + +} // namespace Log4Qt + + +#endif // _DATABASEAPPENDER_H diff --git a/ext/Log4Qt/src/databaselayout.cpp b/ext/Log4Qt/src/databaselayout.cpp new file mode 100755 index 0000000..06cdb34 --- /dev/null +++ b/ext/Log4Qt/src/databaselayout.cpp @@ -0,0 +1,218 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: databaselayout.cpp + * created: March 2010 + * author: Michael Filonenko + * + * + * Copyright 2010 Michael Filonenko + * + * 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 "databaselayout.h" + +#include <QtCore/QDebug> + +#include <QtSql/QSqlField> +#include "loggingevent.h" + +#include "helpers/datetime.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DatabaseLayout + **************************************************************************/ + + QSqlRecord DatabaseLayout::formatRecord(const LoggingEvent &rEvent) + { + QSqlField field; + QSqlRecord record; + + if (!mTimeStamp.isEmpty()) { + field.setName(mTimeStamp); + field.setType(QVariant::DateTime); + field.setGenerated(true); + field.setValue(DateTime::fromMilliSeconds(rEvent.timeStamp())); + record.append(field); + } + + if (!mLoggerName.isEmpty()) { + field.setName(mLoggerName); + field.setType(QVariant::String); + field.setGenerated(true); + field.setValue(rEvent.loggerName()); + record.append(field); + } + + if (!mThreadName.isEmpty()) { + field.setName(mThreadName); + field.setType(QVariant::String); + field.setGenerated(true); + field.setValue(rEvent.threadName()); + record.append(field); + } + + if (!mLevel.isEmpty()) { + field.setName(mLevel); + field.setType(QVariant::String); + field.setGenerated(true); + field.setValue(rEvent.level().toString()); + record.append(field); + } + + if (!mMessage.isEmpty()) { + field.setName(mMessage); + field.setType(QVariant::String); + field.setGenerated(true); + field.setValue(rEvent.message()); + record.append(field); + } + return record; + } + + + QString DatabaseLayout::format(const LoggingEvent &rEvent) + { + QString result; + + if (!mTimeStamp.isEmpty()) { + result.append(mTimeStamp); + result.append(":"); + result.append(DateTime::fromMilliSeconds(rEvent.timeStamp()).toString("dd.MM.yyyy hh:mm")); + } + + if (!mThreadName.isEmpty()) { + result.append(mThreadName); + result.append(":"); + result.append(mThreadName); + result.append("; "); + } + + if (!mLevel.isEmpty()) { + result.append(mLevel); + result.append(":"); + result.append(mLevel); + result.append("; "); + } + + if (!mLoggerName.isEmpty()) { + result.append(mLoggerName); + result.append(":"); + result.append(mLoggerName); + result.append("; "); + } + + if (!mMessage.isEmpty()) { + result.append(mMessage); + result.append(":"); + result.append(mMessage); + result.append("; "); + } + return result; + } + + QString DatabaseLayout::timeStampColumn() const + { + return mTimeStamp; + } + QString DatabaseLayout::loggerNameColumn() const + { + return mLoggerName; + } + QString DatabaseLayout::threadNameColumn() const + { + return mThreadName; + } + + QString DatabaseLayout::levelColumn() const + { + return mLevel; + } + + QString DatabaseLayout::messageColumn() const + { + return mMessage; + } + + + void DatabaseLayout::setTimeStampColumn(const QString& columnName) + { + mTimeStamp = columnName; + } + + void DatabaseLayout::setLoggerNameColumn(const QString& columnName) + { + mLoggerName = columnName; + } + + void DatabaseLayout::setThreadNameColumn(const QString& columnName) + { + mThreadName = columnName; + } + + void DatabaseLayout::setLevelColumn(const QString& columnName) + { + mLevel = columnName; + } + + void DatabaseLayout::setMessageColumn(const QString& columnName) + { + mMessage = columnName; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DatabaseLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DatabaseLayout(" + << "name:" << name() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/databaselayout.h b/ext/Log4Qt/src/databaselayout.h new file mode 100755 index 0000000..4e22121 --- /dev/null +++ b/ext/Log4Qt/src/databaselayout.h @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: databaselayout.h + * created: March 2010 + * author: Michael Filonenko + * + * + * Copyright 2010 Michael Filonenko + * + * 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_DATABASELAYOUT_H +#define LOG4QT_DATABASELAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "layout.h" + +#include <QtSql/QSqlRecord> + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class DatabaseLayout outputs loggin event into sql table. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT DatabaseLayout : public Layout + { + Q_OBJECT + + /*! + The property holds column name to save timestamp of log event + */ + Q_PROPERTY(QString timeStampColumn READ timeStampColumn WRITE setTimeStampColumn) + /*! + The property holds column name to save logger name of log event + */ + Q_PROPERTY(QString loggerNameColumn READ loggerNameColumn WRITE setLoggerNameColumn) + /*! + The property holds column name to save thread name of log event + */ + Q_PROPERTY(QString threadNameColumn READ threadNameColumn WRITE setThreadNameColumn) + /*! + The property holds column name to save level of log event + */ + Q_PROPERTY(QString levelColumn READ levelColumn WRITE setLevelColumn) + /*! + The property holds column name to save message of log event + */ + Q_PROPERTY(QString messageColumn READ messageColumn WRITE setMessageColumn) + + + public: + DatabaseLayout(QObject *pParent = 0); + // virtual ~DatabaseLayout(); // Use compiler default + private: + DatabaseLayout(const DatabaseLayout &rOther); // Not implemented + DatabaseLayout &operator=(const DatabaseLayout &rOther); // Not implemented + + public: + virtual QSqlRecord formatRecord(const LoggingEvent &rEvent); + virtual QString format(const LoggingEvent &rEvent); + + QString timeStampColumn() const; + QString loggerNameColumn() const; + QString threadNameColumn() const; + QString levelColumn() const; + QString messageColumn() const; + + void setTimeStampColumn(const QString& columnName); + void setLoggerNameColumn(const QString& columnName); + void setThreadNameColumn(const QString& columnName); + void setLevelColumn(const QString& columnName); + void setMessageColumn(const QString& columnName); + + protected: + + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %DatabaseLayout(name:"SL" referencecount:1) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + private: + QString mTimeStamp; + QString mLoggerName; + QString mThreadName; + QString mLevel; + QString mMessage; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DatabaseLayout::DatabaseLayout(QObject *pParent) : + Layout(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DatabaseLayout, Q_COMPLEX_TYPE); // Use default + +#endif // LOG4QT_DATABASELAYOUT_H diff --git a/ext/Log4Qt/src/fileappender.cpp b/ext/Log4Qt/src/fileappender.cpp new file mode 100755 index 0000000..717d767 --- /dev/null +++ b/ext/Log4Qt/src/fileappender.cpp @@ -0,0 +1,317 @@ +/****************************************************************************** + * + * package: + * file: fileappender.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 "fileappender.h" + +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> +#include <QtCore/QTextCodec> +#include "layout.h" +#include "loggingevent.h" + +// if we are in WIN* +#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) +#include <windows.h> +#endif + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: FileAppender + **************************************************************************/ + + + FileAppender::FileAppender(QObject *pParent) : + WriterAppender(pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(false), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(true), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent) : + WriterAppender(pLayout, pParent), + mAppendFile(append), + mBufferedIo(buffered), + mFileName(rFileName), + mpFile(0), + mpTextStream(0) + { + } + + + FileAppender::~FileAppender() + { + close(); + } + + + void FileAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (mFileName.isEmpty()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires file and has no file set"), + APPENDER_ACTIVATE_MISSING_FILE_ERROR); + e << name(); + logger()->error(e); + return; + } + closeFile(); + openFile(); + WriterAppender::activateOptions(); + } + + + void FileAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + WriterAppender::close(); + closeFile(); + } + + + bool FileAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "FileAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!mpFile || !mpTextStream) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without open file"), + APPENDER_NO_OPEN_FILE_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return WriterAppender::checkEntryConditions(); + } + + + void FileAppender::closeFile() + { + // Q_ASSERT_X(, "FileAppender::closeFile()", "Lock must be held by caller") + + if (mpFile) + logger()->debug("Closing file '%1' for appender '%2'", mpFile->fileName(), name()); + + setWriter(0); + delete mpTextStream; + mpTextStream = 0; + delete mpFile; + mpFile = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug FileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "FileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool FileAppender::handleIoErrors() const + { + // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller") + + if (mpFile->error() == QFile::NoError) + return false; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to write to file '%1' for appender '%2'"), + APPENDER_WRITING_FILE_ERROR); + e << mFileName << name(); + e.addCausingError(LogError(mpFile->errorString(), mpFile->error())); + logger()->error(e); + return true; + } + + + void FileAppender::openFile() + { + Q_ASSERT_X(mpFile == 0 && mpTextStream == 0, "FileAppender::openFile()", "Opening file without closing previous file"); + + QFileInfo file_info(mFileName); + QDir parent_dir = file_info.dir(); + if (!parent_dir.exists()) + { + logger()->trace("Creating missing parent directory for file %1", mFileName); + QString name = parent_dir.dirName(); + parent_dir.cdUp(); + parent_dir.mkdir(name); + } + +#if defined(__WIN32__) || defined(WIN) || defined(WIN32) || defined(Q_OS_WIN32) + // Let windows resolve any environment variables included in the file path + wchar_t buffer[MAX_PATH]; + if (ExpandEnvironmentStringsW((wchar_t*)mFileName.utf16(), buffer, MAX_PATH)) { + mFileName = QString::fromWCharArray(buffer); + } +#endif + + mpFile = new QFile(mFileName); + QFile::OpenMode mode = QIODevice::WriteOnly | QIODevice::Text; + if (mAppendFile) + mode |= QIODevice::Append; + else + mode |= QIODevice::Truncate; + if (!mBufferedIo) + mode |= QIODevice::Unbuffered; + 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; + } + mpTextStream = new QTextStream(mpFile); + setWriter(mpTextStream); + logger()->debug("Opened file '%1' for appender '%2'", mpFile->fileName(), name()); + } + + + bool FileAppender::removeFile(QFile &rFile) const + { + if (rFile.remove()) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to remove file '%1' for appender '%2'"), + APPENDER_REMOVE_FILE_ERROR); + e << rFile.fileName() << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + bool FileAppender::renameFile(QFile &rFile, + const QString &rFileName) const + { + logger()->debug("Renaming file '%1' to '%2'", rFile.fileName(), rFileName); + if (rFile.rename(rFileName)) + return true; + + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Unable to rename file '%1' to '%2' for appender '%3'"), + APPENDER_RENAMING_FILE_ERROR); + e << rFile.fileName() << rFileName << name(); + e.addCausingError(LogError(rFile.errorString(), rFile.error())); + logger()->error(e); + return false; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/fileappender.h b/ext/Log4Qt/src/fileappender.h new file mode 100755 index 0000000..6234af5 --- /dev/null +++ b/ext/Log4Qt/src/fileappender.h @@ -0,0 +1,233 @@ +/****************************************************************************** + * + * package: + * file: fileappender.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 _FILEAPPENDER_H +#define _FILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "writerappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QFile; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class FileAppender appends log events to a file. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT FileAppender : public WriterAppender + { + Q_OBJECT + + /*! + * The property holds, if the output is appended to the file. + * + * The default is false for not appending. + * + * \sa appendFile(), setAppendFile() + */ + Q_PROPERTY(bool appendFile READ appendFile WRITE setAppendFile) + + /*! + * The property holds, if the output is buffered. + * + * The default is true for buffering. + * + * \sa bufferedIo(), setBufferedIo() + */ + Q_PROPERTY(bool bufferedIo READ bufferedIo WRITE setBufferedIo) + + /*! + * The property holds the name of the file. + * + * \sa file(), setFile() + */ + Q_PROPERTY(QString file READ file WRITE setFile) + + public: + FileAppender(QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + FileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + bool buffered, + QObject *pParent = 0); + virtual ~FileAppender(); + private: + FileAppender(const FileAppender &rOther); // Not implemented + FileAppender &operator=(const FileAppender &rOther); // Not implemented + + public: + bool appendFile() const; + QString file() const; + bool bufferedIo() const; + // JAVA: int bufferSize() const; + void setAppendFile(bool append); + void setBufferedIo(bool buffered); + // JAVA: void setBufferSize(int bufferSize); + void setFile(const QString &rFileName); + + virtual void activateOptions(); + virtual void close(); + + protected: + /*! + * Tests if all entry conditions for using append() in this class are met. + * + * If a conditions is not met, an error is logged and the function returns + * false. Otherwise the result of WriterAppender::checkEntryConditions() + * is returned. + * + * The checked conditions are: + * - That a file is set and open (APPENDER_NO_OPEN_FILE_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeFile(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %FileAppender(name:"FA" appendfile:false bufferedio:true encoding:"" + * file:"log.txt" filter: 0x0 immediateflush:true isactive:false + * isclosed:false layout:"TTCC" referencecount:2 + * threshold:"NULL" writer:0x0) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Checks for file I/O errrors. If an error is found it is logged and the + * function returns true. Otherwise false is returned. + */ + virtual bool handleIoErrors() const; + + /*! + * Opens the file for the appender based on the specified file name and + * mode. A text stream is created and passed on to the super class + * WriterAppender. + * + * If the parent directory of the specified file does not exists, + * it is created. + */ + void openFile(); + + /*! + * Removes the file \a rFile. If the operation is successful, true is + * returned. Otherwise an APPENDER_REMOVE_FILE_ERROR error is logged + * and false is returned. + */ + bool removeFile(QFile &rFile) const; + + /*! + * Renames the file \a rFile to \a rFileName. If the operation is + * successful, true is returned. Otherwise an + * APPENDER_RENAMING_FILE_ERROR error is logged and false is returned. + */ + bool renameFile(QFile &rFile, + const QString &rFileName) const; + + // JAVA: void setQWForFiles(Writer writer); + + private: + volatile bool mAppendFile; + volatile bool mBufferedIo; + QString mFileName; + QFile *mpFile; + QTextStream *mpTextStream; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool FileAppender::appendFile() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAppendFile; } + + inline QString FileAppender::file() const + { QMutexLocker locker(&mObjectGuard); + return mFileName; } + + inline bool FileAppender::bufferedIo() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mBufferedIo; } + + inline void FileAppender::setAppendFile(bool append) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mAppendFile = append; } + + inline void FileAppender::setBufferedIo(bool buffered) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mBufferedIo = buffered; } + + inline void FileAppender::setFile(const QString &rFileName) + { QMutexLocker locker(&mObjectGuard); + mFileName = rFileName; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(::FileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // _FILEAPPENDER_H 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 diff --git a/ext/Log4Qt/src/hierarchy.cpp b/ext/Log4Qt/src/hierarchy.cpp new file mode 100755 index 0000000..90a5cf6 --- /dev/null +++ b/ext/Log4Qt/src/hierarchy.cpp @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * package: + * file: hierarchy.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * 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 "hierarchy.h" + +#include <QtCore/QDebug> +#include "logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, ::LoggerRepository) + + + + /************************************************************************** + * Class implementation: Hierarchy + **************************************************************************/ + + + Hierarchy::Hierarchy() : +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + mObjectGuard(), +#else + mObjectGuard(QReadWriteLock::Recursive), +#endif + mLoggers(), + mThreshold(Level::NULL_INT), + mpRootLogger(logger(QString())) + { + // Store root logger to allow rootLogger() to be const + } + + + Hierarchy::~Hierarchy() + { + static_logger()->warn("Unexpected destruction of Hierarchy"); + + // QWriteLocker locker(&mObjectGuard); + // + // resetConfiguration(); + // clear(); + // delete mpRootLogger; + } + + + bool Hierarchy::exists(const QString &rName) const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.contains(rName); + } + + + Logger *Hierarchy::logger(const QString &rName) + { + QWriteLocker locker(&mObjectGuard); + + return createLogger(rName); + } + + + QList<Logger *> Hierarchy::loggers() const + { + QReadLocker locker(&mObjectGuard); + + return mLoggers.values(); + } + + + void Hierarchy::setThreshold(const QString &rThreshold) + { + setThreshold(Level::fromString(rThreshold)); + } + + + void Hierarchy::resetConfiguration() + { + QWriteLocker locker(&mObjectGuard); + + // Reset all loggers. + // Leave log, qt and root logger to the last to allow debugging of shutdown. + + Logger *p_logging_logger = logger(QLatin1String("")); + Logger *p_qt_logger = logger(QLatin1String("Qt")); + Logger *p_root_logger = rootLogger(); + + Logger *p_logger; + Q_FOREACH(p_logger, mLoggers) + { + if ((p_logger == p_logging_logger) || (p_logger == p_qt_logger) || (p_logger == p_root_logger)) + continue; + resetLogger(p_logger, Level::NULL_INT); + } + resetLogger(p_qt_logger, Level::NULL_INT); + resetLogger(p_logging_logger, Level::NULL_INT); + resetLogger(p_root_logger, Level::DEBUG_INT); + } + + + void Hierarchy::shutdown() + { + static_logger()->debug("Shutting down Hierarchy"); + resetConfiguration(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug Hierarchy::debug(QDebug &rDebug) const + { + rDebug.nospace() << "Hierarchy(" + << "loggers:" << loggers().count() << " " + << "threshold:" << threshold().toString() << " " + << "root-level:" << rootLogger()->level().toString() << " " + << "root-appenders:" << rootLogger()->appenders().count() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + Logger *Hierarchy::createLogger(const QString &rName) + { + // Q_ASSERT_X(, "Hierarchy::createLogger", "Lock must be held by caller") + + const QString name_separator = QLatin1String("::"); + + Logger *p_logger = mLoggers.value(rName, 0); + if (p_logger != 0) + return p_logger; + + if (rName.isEmpty()) + { + p_logger = new Logger(this, Level::DEBUG_INT, QLatin1String("root"), 0); + mLoggers.insert(QString(), p_logger); + return p_logger; + } + QString parent_name; + int index = rName.lastIndexOf(name_separator); + if (index >=0) + parent_name = rName.left(index); + p_logger = new Logger(this, Level::NULL_INT, rName, createLogger(parent_name)); + mLoggers.insert(rName, p_logger); + return p_logger; + } + + + void Hierarchy::resetLogger(Logger *pLogger, Level level) const + { + // Q_ASSERT_X(, "Hierarchy::resetLogger", "Lock must be held by caller") + + pLogger->removeAllAppenders(); + pLogger->setAdditivity(true); + pLogger->setLevel(level); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/hierarchy.h b/ext/Log4Qt/src/hierarchy.h new file mode 100755 index 0000000..3199523 --- /dev/null +++ b/ext/Log4Qt/src/hierarchy.h @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * package: + * file: hierarchy.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 _HIERARCHY_H +#define _HIERARCHY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "loggerrepository.h" + +#include <QtCore/QHash> +#include <QtCore/QReadWriteLock> + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Hierarchy implements a logger repository. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT Hierarchy : public LoggerRepository + { + public: + Hierarchy(); + // Hierarchy(const Hierarchy &rOther); // Use compiler default + virtual ~Hierarchy(); + // Hierarchy &operator=(const Hierarchy &rOther); // Use compiler default + + public: + virtual bool exists(const QString &rName) const; + virtual Logger *logger(const QString &rName); + virtual QList<Logger *> loggers() const; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual Logger *rootLogger() const; + virtual Level threshold() const; + virtual void setThreshold(Level level); + virtual void setThreshold(const QString &rThreshold); + + // JAVA: void clear(); + virtual bool isDisabled(Level level); + virtual void resetConfiguration(); + virtual void shutdown(); + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + // JAVA: void addRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + // JAVA: QHash<QString, ObjectRenderer *> getRendererMap() const; + // JAVA: setRenderer(const QString &rClass, ObjectRenderer *pObjectRenderer); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * <tt> + * %Hierarchy(loggers:6 threshold:"ALL" root-level:"DEBUG" root-appenders:0) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rdebug) const; +#endif + + private: + Logger *createLogger(const QString &rName); + void resetLogger(Logger *pLogger, Level level) const; + + private: + mutable QReadWriteLock mObjectGuard; + QHash<QString, Logger*> mLoggers; + volatile bool mHandleQtMessages; + Level mThreshold; + Logger *mpRootLogger; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Logger *Hierarchy::rootLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpRootLogger; } + + inline Level Hierarchy::threshold() const + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return mThreshold; } + + inline void Hierarchy::setThreshold(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + mThreshold = level; } + + inline bool Hierarchy::isDisabled(Level level) + { // QReadLocker locker(&mObjectGuard); // Level is threadsafe + return level < mThreshold; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(::Hierarchy, Q_COMPLEX_TYPE); // Use default + + +#endif // _HIERARCHY_H diff --git a/ext/Log4Qt/src/layout.cpp b/ext/Log4Qt/src/layout.cpp new file mode 100644 index 0000000..19c5059 --- /dev/null +++ b/ext/Log4Qt/src/layout.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.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 "layout.h" + +#include <QtCore/QDebug> +#include "loggingevent.h" +#include "logmanager.h" + + + +namespace Log4Qt +{ + + + /*************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Layout + **************************************************************************/ + + + QString Layout::contentType() const + { + return QString::fromLatin1("text/plain"); + } + + + void Layout::activateOptions() + { + } + + + QString Layout::endOfLine() + { + // There seams to be no function in Qt for this. MinGW enter '\r\n' automatically + return QLatin1String("\n"); + } + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/layout.h b/ext/Log4Qt/src/layout.h new file mode 100755 index 0000000..1946454 --- /dev/null +++ b/ext/Log4Qt/src/layout.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: layout.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_LAYOUT_H +#define LOG4QT_LAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "helpers/logobject.h" + +#include "helpers/logobjectptr.h" +#include "log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Layout is the base class for all layouts. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT Layout : public LogObject + { + Q_OBJECT + + /*! + * The property holds the content type of the layout. + * + * \sa contentType() + */ + Q_PROPERTY(QString footercontentType READ contentType) + /*! + * The property holds the footer used by the layout. + * + * \sa footer(), setFooter() + */ + Q_PROPERTY(QString footer READ footer WRITE setFooter) + /*! + * The property holds the header used by the layout. + * + * \sa header(), setHeader() + */ + Q_PROPERTY(QString header READ header WRITE setHeader) + + public: + Layout(QObject *pParent = 0); + virtual ~Layout(); + private: + Layout(const Layout &rOther); // Not implemented + Layout &operator=(const Layout &rOther); // Not implemented + + public: + virtual QString contentType() const; + QString footer() const; + QString header() const; + // JAVA: virtual bool ignoresThrowable() const; + QString name() const; + void setFooter(const QString &rFooter); + void setHeader(const QString &rHeader); + void setName(const QString &rName); + // JAVA: void setIgnoresThrowable(bool) const; + + virtual void activateOptions(); + virtual QString format(const LoggingEvent &rEvent) = 0; + + /*! + * Returns the end of line seperator for the operating system. + * + * Windows: \\r\\n + * Mac: \\r + * UNIX: \\n + */ + static QString endOfLine(); + + // Member variables + private: + QString mFooter; + QString mHeader; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Layout::Layout(QObject *pParent) : + LogObject(pParent) + {} + + inline Layout::~Layout() + {} + + inline QString Layout::footer() const + { return mFooter; } + + inline QString Layout::header() const + { return mHeader; } + + inline QString Layout::name() const + { return objectName(); } + + inline void Layout::setFooter(const QString &rFooter) + { mFooter = rFooter; } + + inline void Layout::setHeader(const QString &rHeader) + { mHeader = rHeader; } + + inline void Layout::setName(const QString &rName) + { setObjectName(rName); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Layout, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<Log4Qt::Layout>, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LAYOUT_H diff --git a/ext/Log4Qt/src/level.cpp b/ext/Log4Qt/src/level.cpp new file mode 100755 index 0000000..f546740 --- /dev/null +++ b/ext/Log4Qt/src/level.cpp @@ -0,0 +1,242 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.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 "level.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDebug> +#include "logger.h" +#include <QDataStream> + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::Level) + + + + /************************************************************************** + * Class implementation: Level + **************************************************************************/ + + + int Level::syslogEquivalent() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + switch (mValue) + { + case NULL_INT: + case ALL_INT: + case TRACE_INT: + case DEBUG_INT: + return 7; + case INFO_INT: + return 6; + case WARN_INT: + return 4; + case ERROR_INT: + return 3; + case FATAL_INT: + case OFF_INT: + return 0; + default: + Q_ASSERT_X(false, "Level::syslogEquivalent()", "Unknown level value"); + return 7; + } + } + + + QString Level::toString() const + { + // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + + const char *p_context = "Level"; + + switch (mValue) + { + case NULL_INT: + return QCoreApplication::translate(p_context, "NULL"); + case ALL_INT: + return QCoreApplication::translate(p_context, "ALL"); + case TRACE_INT: + return QCoreApplication::translate(p_context, "TRACE"); + case DEBUG_INT: + return QCoreApplication::translate(p_context, "DEBUG"); + case INFO_INT: + return QCoreApplication::translate(p_context, "INFO"); + case WARN_INT: + return QCoreApplication::translate(p_context, "WARN"); + case ERROR_INT: + return QCoreApplication::translate(p_context, "ERROR"); + case FATAL_INT: + return QCoreApplication::translate(p_context, "FATAL"); + case OFF_INT: + return QCoreApplication::translate(p_context, "OFF"); + default: + Q_ASSERT_X(false, "Level::toString()", "Unknown level value"); + return QCoreApplication::translate(p_context, "NULL"); + } + } + + + Level Level::fromString(const QString &rLevel, bool *pOk) + { + const char *p_context = "Level"; + if (pOk) + *pOk = true; + + if (rLevel == QLatin1String("OFF") || + rLevel == QCoreApplication::translate(p_context, "OFF")) + return OFF_INT; + if (rLevel == QLatin1String("FATAL") || + rLevel == QCoreApplication::translate(p_context, "FATAL")) + return FATAL_INT; + if (rLevel == QLatin1String("ERROR") || + rLevel == QCoreApplication::translate(p_context, "ERROR")) + return ERROR_INT; + if (rLevel == QLatin1String("WARN") || + rLevel == QCoreApplication::translate(p_context, "WARN")) + return WARN_INT; + if (rLevel == QLatin1String("INFO") || + rLevel == QCoreApplication::translate(p_context, "INFO")) + return INFO_INT; + if (rLevel == QLatin1String("DEBUG") || + rLevel == QCoreApplication::translate(p_context, "DEBUG")) + return DEBUG_INT; + if (rLevel == QLatin1String("TRACE") || + rLevel == QCoreApplication::translate(p_context, "TRACE")) + return TRACE_INT; + if (rLevel == QLatin1String("ALL") || + rLevel == QCoreApplication::translate(p_context, "ALL")) + return ALL_INT; + if (rLevel == QLatin1String("NULL") || + rLevel == QCoreApplication::translate(p_context, "NULL")) + return NULL_INT; + + logger()->warn("Use of invalid level string '%1'. Using 'Level::NULL_INT' instead.", rLevel); + if (pOk) + *pOk = false; + return NULL_INT; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel) + { + quint8 l = rLevel.mValue; + rStream << l; + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel) + { + quint8 l; + rStream >> l; + rLevel.mValue = static_cast<Level::Value>(l); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const Level &rLevel) + { + debug.nospace() << "Level(" + << rLevel.toString() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + +Level::Level(Value value) + : mValue(value) +{ +} + +int Level::toInt() const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue; +} + +bool Level::operator==(const Level &rOther) const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue == rOther.mValue; +} + +bool Level::operator!=(const Level &rOther) const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue != rOther.mValue; +} + +bool Level::operator<(const Level &rOther) const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue < rOther.mValue; +} + +bool Level::operator<=(const Level &rOther) const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue <= rOther.mValue; +} + +bool Level::operator>(const Level &rOther) const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue > rOther.mValue; +} + +bool Level::operator>=(const Level &rOther) const +{ // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mValue >= rOther.mValue; +} + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/level.h b/ext/Log4Qt/src/level.h new file mode 100755 index 0000000..056e82a --- /dev/null +++ b/ext/Log4Qt/src/level.h @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: level.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_LEVEL_H +#define LOG4QT_LEVEL_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QString> +#include <QtCore/QMetaType> +#include "log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class Level defines the level of a logging event. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT Level + { + public: + // Comparisson operators rely on the order: + // NULL_INT < ALL_INT < TRACE_INT < ... + // Serialisation uses unsigned 8 bit int + + /*! + * The enumeration Value contains all possible Level values. + */ + enum Value + { + /*! NULL_INT is used for no level has been specified */ + NULL_INT = 0, + ALL_INT = 32, + TRACE_INT = 64, + DEBUG_INT = 96, + INFO_INT = 128, + WARN_INT = 150, + ERROR_INT = 182, + FATAL_INT = 214, + OFF_INT = 255 + }; + + public: + Level(Value value = NULL_INT); + // Level(const Level &rOther); // Use compiler default + // virtual ~Level(); // Use compiler default + // Level &operator=(const Level &rOther); // Use compiler default + + int syslogEquivalent() const; + int toInt() const; + + bool operator==(const Level &rOther) const; + bool operator!=(const Level &rOther) const; + bool operator<(const Level &rOther) const; + bool operator<=(const Level &rOther) const; + bool operator>(const Level &rOther) const; + bool operator>=(const Level &rOther) const; + QString toString() const; + + static Level fromString(const QString &rName, bool *pOk = 0); + + private: + // QMutex mObjectGuard; + volatile Value mValue; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + friend QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates Level + * + * Writes the given error \a rLevel to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const Level &rLevel); + + /*! + * \relates Level + * + * Reads an error from the given stream \a rStream into the given + * error \a rLevel, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + Level &rLevel); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Level + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %Level("ERROR") + * </tt> + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const Level &rLevel); +#endif // QT_NO_DEBUG_STREAM + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::Level) +Q_DECLARE_TYPEINFO(Log4Qt::Level, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LEVEL_H diff --git a/ext/Log4Qt/src/log4qt.cpp b/ext/Log4Qt/src/log4qt.cpp new file mode 100755 index 0000000..430b022 --- /dev/null +++ b/ext/Log4Qt/src/log4qt.cpp @@ -0,0 +1,15 @@ +//============================================================================ +// Name : log4qt.cpp +// Author : +// Version : +// Copyright : Your copyright notice +// Description : Hello World in C++, Ansi-style +//============================================================================ + +#include <iostream> +using namespace std; + +int main() { + cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! + return 0; +} diff --git a/ext/Log4Qt/src/log4qt.h b/ext/Log4Qt/src/log4qt.h new file mode 100644 index 0000000..b3c32ed --- /dev/null +++ b/ext/Log4Qt/src/log4qt.h @@ -0,0 +1,623 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logging.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Added a compile time version check for the Qt version + * Jan 2009, Martin Heinrich: + * - Updated documentation and version information for version 0.2 + * Feb 2009, Martin Heinrich: + * - Updated version information for version 0.3 + * + * + * 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_H +#define LOG4QT_H + +#include "log4qtshared.h" + +/*! + * \page Log4Qt Main Page + * + * %Log4Qt is a C++ port of the Apache Software Foundation Log4j package + * using the Trolltech Qt Framework. + * + * The documentation describes classes and methods that have been added or + * changed compared to Log4j. + * + * The following sections are describing the implementation in more detail: + * - \ref Changes "Differences to Log4j" + * - \ref Ownership "Object ownership" + * - \ref LogLog "Logging within the package" + * - \ref Init "Initialization procedure" + * - \ref Env "Environment Variables" + * - \ref Undocumented "Undocumented functions" + * - \ref Assumptions "Assumptions" + * + * \author Martin Heinrich + * \version 0.3 (January 2009) + * + */ + +/*! + * \page Changes Differences to Log4j + * + * The following fundamental differences exist between %Log4Qt and Log4j: + * + * - As a JAVA package Log4j does not have to manage object ownership and + * lifetime in the same way then it is required in C++. For details on + * how object ownership is handled see \ref Ownership "Object ownership". + * - The package uses itself for its internal logging similar to Log4j 1.3. + * For details see \ref LogLog "Logging within the package". + * - The configuration using system properties was replaced with a combination + * of environment variables and application settings. For details see + * \ref Env "Environment Variables". + * - Custom levels are not supported. + * - Multiple Logger Repositories are not supported + * + * The following classes have been changed: + * + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - The procedure of checking, if logging is possible, originally used by + * \ref Log4Qt::WriterAppender "WriterAppender" was generalised and is used + * in \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" and derived classes + * (\ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()"). + * - The \ref Log4Qt::AppenderSkeleton::doAppend() "doAppend()" member function will + * check the entry conditions by calling the sub-class specific + * \ref Log4Qt::AppenderSkeleton::checkEntryConditions() "checkEntryConditions()". + * If successful the sub-class specific + * \ref Log4Qt::AppenderSkeleton::append() "append()" function is called. + * + * - Configurator + * - Configure functions return a boolean indicating, if the configuration + * was successful. + * - Configure errors are accessible over + * \ref Log4Qt::ConfiguratorHelper::configureError() + * "ConfiguratorHelper::configureError()". + * - Watching for configuration file changes is a function performed + * centrally by the \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper". + * The class provides signals to notify on configuration change and errors. + * - The class \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" was + * extended to be able to read configuration data from a QSettings object. + * + * - \ref Log4Qt::Level "Level" + * - A new value \ref Log4Qt::Level::NULL_INT "Level::NULL_INT" was + * introduced to indicate there is no level set. + * + * - \ref Log4Qt::Logger "Logger" + * - The method \ref Log4Qt::Logger::isEnabledFor() "isEnabledFor()" + * does also take the repository threshold into account. + * - Several overloaded convenience member function are available to log + * messages with arguments of different types. + * - Two macros, \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * and \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER", + * allows retrieving and caching of a pointer to a logger object. + * + * - \ref Log4Qt::LogManager "LogManager" + * - A QtMessage handler can be installed via + * \ref Log4Qt::LogManager::setHandleQtMessages() "setHandleQtMessages()", + * to redirect all messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() to a logger. The logger is named Qt and can be + * accessed using \ref Log4Qt::LogManager::qtLogger() "qtLogger()". + * - The initialisation procedure is available over a public method + * (\ref Log4Qt::LogManager::startup() "startup()"). + * - The LogManager provides access to the logger used internally by the + * package (\ref Log4Qt::LogManager::logLogger() "logLogger()") and to + * its default initialisation procedure + * (\ref Log4Qt::LogManager::configureLogLogger() "configureLogLogger()"). + * + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - The class will call \ref Log4Qt::WriterAppender::handleIoErrors() + * "handleIoErrors()" after all I/O operations. Sub-classes should + * re-implement the function to handle errors. + * + * The following classes have been added: + * + * - An additional appender class, \ref Log4Qt::DebugAppender "DebugAppender", + * was added. The class appends logging events to the platform specific debug + * output. + * - Various helper class have been introduced: + * - \ref Log4Qt::ClassLogger "ClassLogger": The class ClassLogger provides + * logging for a QObject derived class. + * - \ref Log4Qt::ConfiguratorHelper "ConfiguratorHelper": The class + * ConfiguratorHelper provides a configuration file watch and last error + * for configurator classes. + * - \ref Log4Qt::DateTime "DateTime": The class DateTime provides extended + * functionality for QDateTime. + * - \ref Log4Qt::LogError "LogError": The class LogError represents an error. + * - \ref Log4Qt::Factory "Factory": The class Factory provides factories + * for Appender, Filter and Layout objects. + * - \ref Log4Qt::InitialisationHelper "InitialisationHelper": The class + * InitialisationHelper performs static initialisation tasks. + * - \ref Log4Qt::LogObject "LogObject": The class LogObject is the common + * base class for many classes in the package. + * - \ref Log4Qt::LogObjectPtr "LogObjectPtr": The class LogObjectPtr + * implements automatic reference counting for LogObject objects. + * - \ref Log4Qt::PatternFormatter "PatternFormatter": The class + * PatternFormatter formats a logging event based on a pattern string. + * - \ref Log4Qt::Properties "Properties": The class Properties implements a + * JAVA property hash. + */ + +/*! + * \page Ownership Object ownership + * + * In difference to the JAVA Log4j package %Log4Qt must manage ownership and + * lifetime of the objects used. This is non trivial as objects are created + * and used in different ways. + * + * In general an object can be created explicitly for example an application + * may create Loggers, Appenders and Layouts during creation of a QApplication + * object. But they can also be automatically created by the package on + * startup using a \ref Log4Qt::PropertyConfigurator "PropertyConfigurator" + * configuration file. Objects may also be created the one way and then used + * the other. Object may be used by multiple other objects. A Layout for example + * may be used by multiple Appenders. Objects are also created from multiple + * threads. The creation may happen during static initialisation and the + * deletion during static de-initialization. + * + * The parent child model used by QObject cannot be used to handle this. It + * cannot automatically delete an object that is used by multiple others as + * for example an Appender used by multiple Loggers. In addition to this + * QObjects and their children must reside in the same thread. This would + * either mean to impose restriction on how objects can be created or to move + * objects to a specific thread. + * + * To allow an automatic deletion of not required objects the package + * implements reference counting for Appenders, Layouts and Filters. The + * reference counting is implemented in \ref Log4Qt::LogObject "LogObject", + * which is used as a common base class. The reference count can be explicitly + * changed using the methods \ref Log4Qt::LogObject::retain() "retain()" and + * \ref Log4Qt::LogObject::release() "release()". Alternatively an auto pointer + * is available \ref Log4Qt::LogObjectPtr "LogObjectPtr", which is used + * throughout the package. + * + * The reference counting mechanism will test, if an object has a QObject + * parent object set. If a parent is set, the object will not be deleted, if + * the reference count reaches 0. This allows to mix the reference counted + * paradigm with the QObject parent child one. + * + * The following example configures a logger and uses reference counting to + * manage the ownership of objects. + * + * \code + * // Create layout + * TTCCLayout *p_layout = new TTCCLayout(); + * + * // Create appender + * ConsoleAppender *p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // p_appender and p_layout are deleted here + * \endcode + * + * The following example configures a logger and uses QObject ownership of + * objects. + * + * \code + * QObject *p_parent = new MyObject; + * + * // Create objects + * ConsoleAppender *p_appender = new ConsoleAppender(p_parent); + * TTCCLayout *p_layout = new TTCCLayout(p_appender); + * + * // Configure appender + * p_appender->setTarget(ConsoleAppender::STDOUT_TARGET); + * p_appender->setLayout(p_layout); + * p_appender->activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(p_appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); + * + * delete p_parent; // p_appender and p_layout are deleted here + * \endcode + * + * The following example shows how to use objects created on the stack. + * + * \code + * { + * // Create layout + * TTCCLayout layout; + * layout.retain(); + * + * // Create appender + * ConsoleAppender appender(&layout, ConsoleAppender::STDOUT_TARGET); + * appender.retain(); + * appender.activateOptions(); + * + * // Get logger + * Logger *p_logger = Logger::logger("MyClass"); + * p_logger->addAppender(&appender); + * + * // ... + * + * // Remove appender from Logger + * p_logger->removeAllAppenders(); // Without retain() program crashes here + * + * } // p_appender and p_layout are deleted here + * \endcode + */ + +/*! + * \page LogLog Logging within the package + * + * The package uses itself for logging similar to Log4j 1.3. This brings much + * more flexibility over logging to stdout, stderr like in Log4j 1.2 using + * logLog. It also enables the program to capture and handle errors raised by + * the package. + * + * Using this approach introduces the issue of recursion. The following example + * explains a situation where this happens. Let's say all logger are configured + * to be additive and only the root logger has an appender set. The appender + * is a \ref Log4Qt::FileAppender "FileAppender". During the logging of an + * event an I/O error occurs. The \ref Log4Qt::FileAppender "FileAppender" logs + * an event by itself using the logger %Log4Qt::FileAppender. The event is + * passed to the root logger, which calls then the \ref Log4Qt::FileAppender + * "FileAppender". This causes another I/O error, which is logged by + * the \ref Log4Qt::FileAppender "FileAppender". + * + * To avoid an endless loop the appender will drop the event on a recursive + * invocation. This check is done by \ref Log4Qt::AppenderSkeleton + * "AppenderSkeleton" in \ref Log4Qt::AppenderSkeleton::doAppend() + * "doAppend()". + * + * The problem only occurs, if a logger, appender, layout or filter log an + * event while an event is appended. Neither the logger class nor any of the + * layout or filter classes log events during appending of an event. Most of + * the appender classes may log errors during appending. Only the + * \ref Log4Qt::ListAppender "ListAppender" and + * \ref Log4Qt::ListAppender "ConsoleAppender" are not logging events. + * + * The default configuration uses two \ref Log4Qt::ListAppender + * "ConsoleAppender", one for stderr and one for stdout. No event will be + * dropped, because no recursive invocations can occur. + */ + +/*! + * \page Init Initialization procedure + * + * The package is initialised in two stages. The first stage takes place during + * static initialization. The second stage takes place when the + * \ref Log4Qt::LogManager "LogManager" singleton is created. + * + * During static initialisation the \ref Log4Qt::InitialisationHelper + * "InitialisationHelper" singleton is created . On construction it captures + * the program startup time, reads the required values from the system + * environment and registers the package types with the Qt type system. + * + * The \ref Log4Qt::LogManager "LogManager" singleton is created on first use. + * The creation is usually triggered by the request for a \ref Log4Qt::Logger + * "Logger" object. The call to \ref Log4Qt::Logger::logger() + * "Logger::logger()" is passed through to \ref Log4Qt::LogManager::logger() + * "LogManager::logger()". On creation the \ref Log4Qt::LogManager "LogManager" + * creates a \ref Log4Qt::Hierarchy "Hierarchy" object as logger repository. + * + * After the singleton is created the logging of the package is configured to + * its default by a call to \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()". The logger + * \ref Log4Qt::LogManager::logLogger() "logLogger()" is configured to be not + * additive. Messages with the level \ref Log4Qt::Level::ERROR_INT + * "Level::ERROR_INT" and \ref Log4Qt::Level::FATAL_INT "Level::FATAL_INT" are + * written to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is read from + * the system environment or application settings using + * \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" with the key \c Debug. If a level value + * is found, but it is not a valid Level string, + * \ref Log4Qt::Level::DEBUG_INT "Level::DEBUG_INT" is used. If no level string + * is found \ref Log4Qt::Level::ERROR_INT "Level::ERROR_INT" is used. + * + * Once the logging is configured the package is initialised by a call to + * \ref Log4Qt::LogManager::startup() "LogManager::startup()". The function + * will test for the setting \c DefaultInitOverride in the system environment + * and application settings using \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()". If the value is present and set to + * anything else then \c false, the initialisation is aborted.<br> + * The system environment and application settings are tested for the setting + * \c Configuration. If it is found and it is a valid path to a file, the + * package is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting \c Configuration is + * not available and a QCoreApplication object is present, the application + * settings are tested for a group \c Properties. If the group exists, + * the package is configured with the setting using the + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration file nor + * configuration settings could be found, the current working directory is + * searched for the file \c "log4qt.properties". If it is found, the package + * is configured with the file using + * \ref Log4Qt::PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * The following example shows how to use application settings to initialise the + * package. + * + * \code + * # file: myapplication.h + * + * #include qapplication.h + * + * class MyApplication : public QApplication + * { + * Q_OBJECT + * + * public: + * MyApplication(); + * ~MyApplication(); + * void setupLog4Qt(); + * } + * \endcode + * \code + * # file: myapplication.cpp + * + * #include myapplication.h + * + * MyApplication::MyApplication( + * { + * // Set Application data to allow Log4Qt initialisation to read the + * // correct values + * setApplicationName("MyApplication"); + * setOrganisationName("MyOrganisation"); + * setOrganizationDomain("www.myorganisation.com"); + * + * // Log first message, which initialises Log4Qt + * Log4Qt::Logger::logger("MyApplication")->info("Hello World"); + * } + * + * MyApplication::~MyApplication() + * { + * } + * + * void MyApplication::setupLog4Qt() + * { + * QSettings s; + * + * // Set logging level for Log4Qt to TRACE + * s.beginGroup("Log4Qt"); + * s.setValue("Debug", "TRACE"); + * + * // Configure logging to log to the file C:/myapp.log using the level TRACE + * s.beginGroup("Properties"); + * s.setValue("log4j.appender.A1", "org.apache.log4j.FileAppender"); + * s.setValue("log4j.appender.A1.file", "C:/myapp.log"); + * s.setValue("log4j.appender.A1.layout", "org.apache.log4j.TTCCLayout"); + * s.setValue("log4j.appender.A1.layout.DateFormat", "ISO8601"); + * s.setValue("log4j.rootLogger", "TRACE, A1"); + * + * // Settings will become active on next application startup + * } + * \endcode + */ + +/*! + * \page Env Environment Variables + * + * The package uses environment variables to control the initialization + * procedure. The environment variables replace the system property entries + * used by Log4j. + * + * For compability reasons the Log4j entry is recognised. Alternatively a + * environment variable style Log4Qt form can be used. The following entries + * are used: + * + * - LOG4QT_DEBUG<br> + * The variable controls the \ref Log4Qt::Level "Level" value for the + * logger \ref Log4Qt::LogManager::logLogger() "LogManager::logLogger()". + * If the value is a valid \ref Log4Qt::Level "Level" string, the level for + * the is set to the level. If the value is not a valid + * \ref Log4Qt::Level "Level" string, \ref Log4Qt::Level::DEBUG_INT + * "DEBUG_INT" is used. Otherwise \ref Log4Qt::Level::ERROR_INT "ERROR_INT" + * is used. + * - \ref Log4Qt::LogManager::configureLogLogger() + * "LogManager::configureLogLogger()" + * + * - LOG4QT_DEFAULTINITOVERRIDE<br> + * The variable controls the \ref Init "initialization procedure" performed + * by the \ref Log4Qt::LogManager "LogManager" on startup. If it is set to + * any other value then \c false the \ref Init "initialization procedure" + * is skipped. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATION<br> + * The variable specifies the configuration file used for initialising the + * package. + * - \ref Log4Qt::LogManager::startup() "LogManager::startup()" + * + * - LOG4QT_CONFIGURATORCLASS<br> + * The variable specifies the configurator class used for initialising the + * package. + * + * Environment variables are read during static initialisation on creation of + * the \ref Log4Qt::InitialisationHelper "InitialisationHelper". They can be + * accessed by calling \ref Log4Qt::InitialisationHelper::environmentSettings() + * "InitialisationHelper::environmentSettings()". + * + * All settings can also be made in the application settings under the group + * \c %Log4Qt. For example the environment variable \c LOG4QT_DEBUG is + * equivalent to the setting \c Debug. If an environment variable is + * set it takes precedence over the application setting. Settings are only + * used, if an QApplication object is available, when the + * \ref Log4Qt::LogManager "LogManager" is + * initialised (see \ref Log4Qt::InitialisationHelper::setting() + * "InitialisationHelper::setting()" for details). + */ + +/*! + * \page Undocumented Undocumented functions + * + * In general it was tried to avoid the usage of undocumented features of Qt. + * Nice to have features like for example Q_DECLARE_PRIVATE are not used. Only + * features that would have been resulted in re-coding the same functionality + * are used. + * + * - QT_WA: The macro is used to call Windows A/W functions + * - \ref Log4Qt::DebugAppender "DebugAppender" + * - QBasicAtomicPointer: The class is used instead of QAtomicPointer, because + * it allows the initialisation as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + * - Q_BASIC_ATOMIC_INITIALIZER: The macro is used to initialise QAtomicPointer + * objects as plain old data type. + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + * - \ref Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" + */ + +/*! + * \page Assumptions Assumptions + * + * The following assumptions are used throughout the package: + * + * - Reading / writing of bool or int is thread-safe, if declared volatile + * - \ref Log4Qt::ListAppender "ListAppender" + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - \ref Log4Qt::ConsoleAppender "ConsoleAppender" + * - \ref Log4Qt::FileAppender "FileAppender" + * - \ref Log4Qt::Hierarchy "Hierarchy" + * - \ref Log4Qt::Level "Level" + * - \ref Log4Qt::Logger "Logger" + * - \ref Log4Qt::WriterAppender "WriterAppender" + * - \ref Log4Qt::Layout::format() "Layout::format()" is implemented reentrant + * in all sub-classes. + * - \ref Log4Qt::AppenderSkeleton "AppenderSkeleton" + * - Being able to use singleton objects during static de-initialization without + * order issues is more valuable then their destruction. + * - \ref Log4Qt::LogManager "LogManager" + * - \ref Log4Qt::LOG4QT_GLOBAL_STATIC "LOG4QT_GLOBAL_STATIC" + * - \ref Log4Qt::LOG4QT_IMPLEMENT_INSTANCE "LOG4QT_IMPLEMENT_INSTANCE" + */ + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/qglobal.h> + +#if QT_VERSION < QT_VERSION_CHECK(4, 3, 0) +# error "Log4Qt requires Qt version 4.3.0 or higher" +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +/*! + * \brief The namespace Log4Qt %Log4Qt encloses all parts of the package. + */ +namespace Log4Qt +{ + /*! + * This macro expands a numeric value of the form 0xMMmmPP (MM = major, + * mm = minor, PP = patch) that specifies Log4Qt's version number. + * This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + // Defined in CMakeLists.txt or pro file + //#define LOG4QT_VERSION 1.0.0 + + /*! + * The macro expands to a string that specifies the Log4Qt's version + * number. This is the version against which the application is compiled. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LogManager::version() "LogManager::version()" + */ + // Defined in CMakeLists.txt or pro file + //#define LOG4QT_VERSION_STR "1.0.0" + + + enum ErrorCode + { + OK = 0, + // AppenderSkeleton, FileAppender, WriterAppender + APPENDER_ACTIVATE_MISSING_LAYOUT_ERROR, + APPENDER_ACTIVATE_MISSING_WRITER_ERROR, + APPENDER_ACTIVATE_MISSING_FILE_ERROR, + APPENDER_CLOSED_ERROR, + APPENDER_INVALID_PATTERN_ERROR, + APPENDER_NO_OPEN_FILE_ERROR, + APPENDER_NOT_ACTIVATED_ERROR, + APPENDER_OPENING_FILE_ERROR, + APPENDER_RENAMING_FILE_ERROR, + APPENDER_REMOVE_FILE_ERROR, + APPENDER_USE_INVALID_PATTERN_ERROR, + APPENDER_USE_MISSING_LAYOUT_ERROR, + APPENDER_USE_MISSING_WRITER_ERROR, + APPENDER_WRITING_FILE_ERROR, + // Level + LEVEL_INVALID_LEVEL_STRING, + // Layouts, PatternFormatter + LAYOUT_EXPECTED_DIGIT_ERROR, + LAYOUT_OPTION_IS_NOT_INTEGER_ERROR, + LAYOUT_INTEGER_IS_NOT_POSITIVE_ERROR, + // Logger + LOGGER_INVALID_LEVEL_FOR_ROOT, + // PropertyConfigurator, OptionHandler + CONFIGURATOR_OPENING_FILE_ERROR, + CONFIGURATOR_READING_FILE_ERROR, + CONFIGURATOR_INVALID_SUBSTITUTION_ERROR, + CONFIGURATOR_INVALID_OPTION_ERROR, + CONFIGURATOR_MISSING_APPENDER_ERROR, + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + CONFIGURATOR_MISSING_LAYOUT_ERROR, + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + CONFIGURATOR_PROPERTY_ERROR, + CONFIGURATOR_UNKNOWN_TYPE_ERROR, + APPENDER_MISSING_DATABASE_OR_TABLE_ERROR, + APPENDER_EXEC_SQL_QUERY_ERROR, + APPENDER_INVALID_DATABASE_LAYOUT_ERROR, + APPENDER_TELNET_SERVER_NOT_RUNNING, + APPENDER_ASNC_DISPATCHER_NOT_RUNNING + }; + + + /****************************************************************************** + * Operators, Helpers + ******************************************************************************/ + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + +} // namespace Log4Qt + + +#endif // LOG4QT_H diff --git a/ext/Log4Qt/src/log4qtshared.h b/ext/Log4Qt/src/log4qtshared.h new file mode 100644 index 0000000..f8bd853 --- /dev/null +++ b/ext/Log4Qt/src/log4qtshared.h @@ -0,0 +1,9 @@ +#include <QtCore/QtGlobal> + +#if defined(LOG4QT_EXPORTS) +# define LOG4QT_EXPORT Q_DECL_EXPORT +#elif defined (LOG4QT_IMPORTS) +# define LOG4QT_EXPORT Q_DECL_IMPORT +#else +# define LOG4QT_EXPORT /**/ +#endif diff --git a/ext/Log4Qt/src/logger.cpp b/ext/Log4Qt/src/logger.cpp new file mode 100644 index 0000000..8c66eb0 --- /dev/null +++ b/ext/Log4Qt/src/logger.cpp @@ -0,0 +1,1047 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Fixed problem in Qt 4.4 where QReadWriteLock is by default + * non-recursive. + * + * + * 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 "logger.h" + +#include <QtCore/QDebug> +#include <QtCore/QThread> +#include <QtCore/QCoreApplication> + +#include "appenderskeleton.h" +#include "varia/listappender.h" +#include "loggingevent.h" +#include "log4qt.h" +#include "loggerrepository.h" +#include "logmanager.h" +#include "logstream.h" + +namespace Log4Qt { + + /************************************************************************** + * Declarations + **************************************************************************/ + + /************************************************************************** + * C helper functions + **************************************************************************/ + + /************************************************************************** + * Class implementation: Logger + **************************************************************************/ + + Logger::Logger(LoggerRepository* pLoggerRepository, Level level, + const QString &rName, Logger *pParent) : + QObject(0), + mName(rName), mpLoggerRepository(pLoggerRepository), mAdditivity(true), + mLevel(level), mpParent(pParent) + { + Q_ASSERT_X(pLoggerRepository, "Logger::Logger()", + "Construction of Logger with null LoggerRepository"); + + setObjectName( mName); + } + + Logger::~Logger() + { + logger()->warn("Unexpected destruction of Logger"); + + // QWriteLocker locker(&mObjectGuard); + // + // QMutableListIterator< LogObjectPtr<Appender> > i(mAppenders); + // while (i.hasNext()) + // { + // i.next(); + // i.remove(); + // } + } + + void Logger::setLevel(Level level) + { + // QWriteLocker locker(&mObjectGuard); // Read/Write int is safe + + if ((parentLogger() == 0) && (level == Level::NULL_INT)) { + logger()->warn( + "Invalid root logger level NULL_INT. Using DEBUG_INT instead"); + level = Level::DEBUG_INT; + } + mLevel = level; + } + + // Note: use MainThreadAppender if you want write the log from non-main threads + // within the main trhead + void Logger::callAppenders(const LoggingEvent &rEvent) const + { + QReadLocker locker(&mAppenderGuard); + + Appender *p_appender; + Q_FOREACH(p_appender, mAppenders) + p_appender->doAppend(rEvent); + if (additivity() && (parentLogger() != 0)) + parentLogger()->callAppenders(rEvent); + } + + Level Logger::effectiveLevel() const + { + Q_ASSERT_X(LogManager::rootLogger()->level() != Level::NULL_INT, + "Logger::effectiveLevel()", "Root logger level must not be NULL_INT"); + + QReadLocker locker(&mAppenderGuard); + + const Logger *p_logger = this; + while (p_logger->level() == Level::NULL_INT) + p_logger = p_logger->parentLogger(); + return p_logger->level(); + } + + bool Logger::isEnabledFor(Level level) const + { + if (mpLoggerRepository->isDisabled(level)) + return false; + return (effectiveLevel() <= level); + } + + Logger *Logger::logger(const QString &rName) + { + return LogManager::logger(rName); + } + + Logger *Logger::logger(const char *pName) + { + return LogManager::logger(QLatin1String(pName)); + } + + Logger *Logger::rootLogger() + { + return LogManager::rootLogger(); + } + +#ifndef QT_NO_DEBUG_STREAM + QDebug Logger::debug(QDebug &rDebug) const + { + QReadLocker locker(&mAppenderGuard); + + QString parent_logger; + if (mpParent) + parent_logger = mpParent->name(); + + rDebug.nospace() << "Logger(" << "name:" << name() << " " << "appenders:" + << mAppenders.count() << " " << "additivity:" << mAdditivity << " " + << mLevel << "parentLogger:" << parent_logger << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + void Logger::forcedLog(Level level, const QString &rMessage) const + { + QReadLocker locker(&mAppenderGuard); + + LoggingEvent event(this, level, rMessage); + callAppenders(event); + } + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const Logger &rLogger) + { + return rLogger.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + /************************************************************************** + * Inline + **************************************************************************/ + + bool Logger::additivity() const + { // QReadLocker locker(&mObjectGuard); // Read/Write of int is safe + return mAdditivity; } + + Level Logger::level() const + { // QReadLocker locker(&mObjectGuard); // Level is thread-safe + return mLevel; } + + LoggerRepository *Logger::loggerRepository() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpLoggerRepository; } + + QString Logger::name() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mName; } + + Logger *Logger::parentLogger() const + { // QReadLocker locker(&mObjectGuard); // Constant for object lifetime + return mpParent; } + + void Logger::setAdditivity(bool additivity) + { // QWriteLocker locker(&mObjectGuard); // Read/Write of int is safe + mAdditivity = additivity; } + + // Level operations + + bool Logger::isDebugEnabled() const + { return isEnabledFor(Level::DEBUG_INT); } + + bool Logger::isErrorEnabled() const + { return isEnabledFor(Level::ERROR_INT); } + + bool Logger::isFatalEnabled() const + { return isEnabledFor(Level::FATAL_INT); } + + bool Logger::isInfoEnabled() const + { return isEnabledFor(Level::INFO_INT); } + + bool Logger::isTraceEnabled() const + { return isEnabledFor(Level::TRACE_INT); } + + bool Logger::isWarnEnabled() const + { return isEnabledFor(Level::WARN_INT); } + + // Log operations: debug + + LogStream Logger::debug() const + { return LogStream(*this, Level::DEBUG_INT); } + + void Logger::debug(const LogError &rLogError) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rLogError.toString()); } + + void Logger::debug(const QString &rMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, rMessage); } + + void Logger::debug(const char *pMessage) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::debug(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::debug(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::DEBUG_INT)) + forcedLog(Level::DEBUG_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: error + + LogStream Logger::error() const + { return LogStream(*this, Level::ERROR_INT); } + + void Logger::error(const QString &rMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rMessage); } + + void Logger::error(const LogError &rLogError) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, rLogError.toString()); } + + void Logger::error(const char *pMessage) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage)); } + + void Logger::error(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::error(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::error(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::error(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::ERROR_INT)) + forcedLog(Level::ERROR_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: fatal + + LogStream Logger::fatal() const + { return LogStream(*this, Level::FATAL_INT); } + + void Logger::fatal(const QString &rMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rMessage); } + + void Logger::fatal(const LogError &rLogError) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, rLogError.toString()); } + + void Logger::fatal(const char *pMessage) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::fatal(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1, const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::fatal(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::FATAL_INT)) + forcedLog(Level::FATAL_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: info + + LogStream Logger::info() const + { return LogStream(*this, Level::INFO_INT); } + + void Logger::info(const QString &rMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rMessage); } + + void Logger::info(const LogError &rLogError) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, rLogError.toString()); } + + void Logger::info(const char *pMessage) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage)); } + + void Logger::info(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::info(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::info(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::info(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::INFO_INT)) + forcedLog(Level::INFO_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: log + + LogStream Logger::log(Level level) const + { return LogStream(*this, level); } + + void Logger::log(Level level, + const QString &rMessage) const + { if (isEnabledFor(level)) + forcedLog(level, rMessage); } + + void Logger::log(Level level, + const LogError &rLogError) const + { if (isEnabledFor(level)) + forcedLog(level, rLogError.toString()); } + + void Logger::log(Level level, + const char *pMessage) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(level)) + forcedLog(level, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: trace + + LogStream Logger::trace() const + { return LogStream(*this, Level::TRACE_INT); } + + void Logger::trace(const QString &rMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rMessage); } + + void Logger::trace(const LogError &rLogError) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, rLogError.toString()); } + + void Logger::trace(const char *pMessage) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::trace(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::trace(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::TRACE_INT)) + forcedLog(Level::TRACE_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + // Log operations: warn + + LogStream Logger::warn() const + { return LogStream(*this, Level::WARN_INT); } + + void Logger::warn(const QString &rMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rMessage); } + + void Logger::warn(const LogError &rLogError) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, rLogError.toString()); } + + void Logger::warn(const char *pMessage) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1)); } + + void Logger::warn(const char *pMessage, + int arg1) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2)); } + + void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2)); } + + void Logger::warn(const char *pMessage, + int arg1, + int arg2) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2, rArg3)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1, rArg2).arg(arg3)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(rArg3)); } + + void Logger::warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1).arg(arg2).arg(arg3)); } + + void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(rArg3)); } + + void Logger::warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(rArg2).arg(arg3)); } + + void Logger::warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(rArg3)); } + + void Logger::warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(arg1).arg(arg2).arg(arg3)); } + + void Logger::warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const + { if (isEnabledFor(Level::WARN_INT)) + forcedLog(Level::WARN_INT, QString::fromUtf8(pMessage).arg(rArg1.toString(), rArg2.toString(), rArg3.toString())); } + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/logger.h b/ext/Log4Qt/src/logger.h new file mode 100755 index 0000000..3e04d4e --- /dev/null +++ b/ext/Log4Qt/src/logger.h @@ -0,0 +1,810 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logger.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_LOGGER_H +#define LOG4QT_LOGGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QObject> + +#include <QtCore/QAtomicPointer> +#include <QtCore/QList> +#include <QtCore/QReadWriteLock> +#include "helpers/logerror.h" +#include "helpers/classlogger.h" +#include "helpers/logobjectptr.h" +#include "helpers/appenderattachable.h" +#include "level.h" +#include "logstream.h" + +#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 macro Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER is not thread-safe." +# endif +#endif + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * LOG4QT_DECLARE_STATIC_LOGGER declares a static function \a FUNCTION that + * returns a pointer to a \ref Log4Qt::Logger "Logger" named after \a CLASS. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by calling \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger( #CLASS )". The pointer is stored to be returned on + * subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class not derived from QObject. + * + * \code + * #file: counter.h + * + * #include logger.h + * + * class Counter + * { + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * LOG4QT_DECLARE_STATIC_LOGGER(logger, Counter) + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) : + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)" + */ +#if QT_VERSION < QT_VERSION_CHECK(4, 4, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static Log4Qt::Logger *p_logger = 0; \ + if (!p_logger) \ + { \ + q_atomic_test_and_set_ptr( \ + &p_logger, \ + 0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#elif QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + #define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer<Log4Qt::Logger > p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger; \ + } +#else +#define LOG4QT_DECLARE_STATIC_LOGGER(FUNCTION, CLASS) \ + static Log4Qt::Logger *FUNCTION() \ + { \ + static QBasicAtomicPointer<Log4Qt::Logger > p_logger = \ + Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!p_logger.loadAcquire()) \ + { \ + p_logger.testAndSetOrdered(0, \ + Log4Qt::Logger::logger( #CLASS )); \ + } \ + return p_logger.loadAcquire(); \ + } +#endif + + /*! + * LOG4QT_DECLARE_QCLASS_LOGGER declares member functions to retrieve + * \ref Log4Qt::Logger "Logger" for the class it is used in. + * + * On the first invocation the \ref Log4Qt::Logger "Logger" is requested + * by a call to \ref Log4Qt::Logger::logger(const char *pName) + * "Logger::logger(const char *pName)". The pointer is stored to be + * returned on subsequent invocations. + * + * The following example shows how to use the macro to define a logger to be + * used within a class derived from QObject. + * + * \code + * #file: counter.h + * + * #include qobject.h + * #include logger.h + * + * class Counter : public QObject + * { + * Q_OBJECT + * LOG4QT_DECLARE_QCLASS_LOGGER + * public: + * Counter(); + * Counter(int preset); + * private: + * int mCount; + * } + * \endcode + * \code + * #file: counter.cpp + * + * #include counter.h + * + * Counter::Counter() : + * mCount(0) + * {} + * + * void Counter::Counter(int preset) + * mCount(preset) + * { + * if (preset < 0) + * { + * logger()->warn("Invalid negative counter preset %1. Using 0 instead.", preset); + * mCount = 0; + * } + * } + * \endcode + * + * \note The function created by the macro is thread-safe. + * + * \sa \ref Log4Qt::Logger::logger(const char *pName) "Logger::logger(const char *pName)", + * \ref Log4Qt::ClassLogger "ClassLogger" + */ + #define LOG4QT_DECLARE_QCLASS_LOGGER \ + private: \ + mutable Log4Qt::ClassLogger mLog4QtClassLogger; \ + public: \ + inline Log4Qt::Logger *logger() const \ + { return mLog4QtClassLogger.logger(this); } \ + private: + + class Appender; + class LoggingEvent; + class LoggerRepository; + + /*! + * \brief The class Logger provides logging services. + * + * A pointer to a logger can be retrieved by calling Logger::logger() or + * LogManager::logger() with the class name as argument. Because a logger + * is never destroyed it is possible to store the pointer to the logger. + * This way the lookup of the pointer in the repository is only required + * on the first logging operation. The macros \ref + * Log4Qt::LOG4QT_DECLARE_STATIC_LOGGER "LOG4QT_DECLARE_STATIC_LOGGER" and + * \ref Log4Qt::LOG4QT_DECLARE_QCLASS_LOGGER "LOG4QT_DECLARE_QCLASS_LOGGER" + * provide a thread-safe implementation to store the logger pointer. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT Logger : public QObject, public AppenderAttachable + { + Q_OBJECT + + /*! + * The property holds, if the logger is additive. + * + * The default is true for being additive. + * + * \sa additive(), setAdditive() + */ + Q_PROPERTY(bool additivity READ additivity WRITE setAdditivity) + + /*! + * The property holds the level used by the logger. + * + * The default is Level::NULL_INT. + * \sa level(), setLevel() + */ + Q_PROPERTY(Log4Qt::Level level READ level WRITE setLevel) + + /*! + * The property holds the LoggerRepository of the logger. + * + * \sa loggerRepository() + */ + Q_PROPERTY(LoggerRepository* loggerRepository READ loggerRepository) + + /*! + * The property holds the name of the logger. + * + * \sa name() + */ + Q_PROPERTY(QString name READ name) + + /*! + * The property holds the parent logger of the logger. + * + * \sa parentLogger() + */ + Q_PROPERTY(Logger* parentLogger READ parentLogger) + + LOG4QT_DECLARE_QCLASS_LOGGER + + protected: + Logger(LoggerRepository* pLoggerRepository, Level level, const QString &rName, Logger *pParent = 0); + virtual ~Logger(); + private: + Logger(const Logger &rOther); // Not implemented + Logger &operator=(const Logger &rOther); // Not implemented + + public: + bool additivity() const; + Level level() const; + LoggerRepository *loggerRepository() const; + QString name() const; + Logger *parentLogger() const; + // JAVA: ResourceBundle *resourceBundle() const; + // JAVA: void setResourceBundle(ResourceBundle *pResourceBundle); + void setAdditivity(bool additivity); + virtual void setLevel(Level level); + + void callAppenders(const LoggingEvent &rEvent) const; + + // JAVA: QString resourceBundleString(const QString &rKey) const; + + Level effectiveLevel() const; + bool isDebugEnabled() const; + + /*! + * Checks if this logger is enabled for a given Level \a level. If the + * logger is enabled the function returns true. Otherwise it returns + * false. + * + * A logger is enabled for a level, if the level is greater or equal + * then the repository threshold and greater and equal then the loggers + * effective level. + * + * \sa LoggerRepository::isDisabled(), effectiveLevel() + */ + bool isEnabledFor(Level level) const; + + bool isErrorEnabled() const; + bool isFatalEnabled() const; + bool isInfoEnabled() const; + bool isTraceEnabled() const; + bool isWarnEnabled() const; + + LogStream debug() const; + void debug(const QString &rMessage) const; + void debug(const LogError &rLogError) const; + void debug(const char *pMessage) const; + void debug(const char *pMessage, + const QString &rArg1) const; + void debug(const char *pMessage, + int arg1) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2) const; + void debug(const char *pMessage, + int arg1, + int arg2) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void debug(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void debug(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + LogStream error() const; + void error(const QString &rMessage) const; + void error(const LogError &rLogError) const; + void error(const char *pMessage) const; + void error(const char *pMessage, + const QString &rArg1) const; + void error(const char *pMessage, + int arg1) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void error(const char *pMessage, + const QString &rArg1, int arg2) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2) const; + void error(const char *pMessage, + int arg1, + int arg2) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void error(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void error(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + LogStream fatal() const; + void fatal(const QString &rMessage) const; + void fatal(const LogError &rLogError) const; + void fatal(const char *pMessage) const; + void fatal(const char *pMessage, + const QString &rArg1) const; + void fatal(const char *pMessage, + int arg1) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2) const; + void fatal(const char *pMessage, + int arg1, + int arg2) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void fatal(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void fatal(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + LogStream info() const; + void info(const QString &rMessage) const; + void info(const LogError &rLogError) const; + void info(const char *pMessage) const; + void info(const char *pMessage, + const QString &rArg1) const; + void info(const char *pMessage, + int arg1) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2) const; + void info(const char *pMessage, + int arg1, + int arg2) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void info(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void info(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + LogStream log(Level level) const; + void log(Level level, + const QString &rMessage) const; + void log(Level level, + const LogError &rLogError) const; + void log(Level level, + const char *pMessage) const; + void log(Level level, + const char *pMessage, + const QString &rArg1) const; + void log(Level level, + const char *pMessage, + int arg1) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void log(Level level, + const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void log(Level level, + const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // JAVA: void l7dlog(Level level, + // const QString &rKey); + // JAVA: void l7dlog(Level level, + // const QString &rKey, + // const QList<Object *> rParameters); + + LogStream trace() const; + void trace(const QString &rMessage) const; + void trace(const LogError &rLogError) const; + void trace(const char *pMessage) const; + void trace(const char *pMessage, + const QString &rArg1) const; + void trace(const char *pMessage, + int arg1) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2) const; + void trace(const char *pMessage, + int arg1, + int arg2) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void trace(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void trace(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + LogStream warn() const; + void warn(const QString &rMessage) const; + void warn(const LogError &rLogError) const; + void warn(const char *pMessage) const; + void warn(const char *pMessage, + const QString &rArg1) const; + void warn(const char *pMessage, + int arg1) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2) const; + void warn(const char *pMessage, + int arg1, + int arg2) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + const QString &rArg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + const QString &rArg2, + int arg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + const QString &rArg3) const; + void warn(const char *pMessage, + int arg1, + int arg2, + int arg3) const; + void warn(const char *pMessage, + const QVariant &rArg1, + const QVariant &rArg2, + const QVariant &rArg3) const; + + // LogManager operations + static Logger *logger(const QString &rName); + static Logger *logger(const char *pName); + static Logger *rootLogger(); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %Logger(name:"Log4Qt" appenders:0 additivity:true Level("NULL") + * parentLogger: "root" ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const Appender &rAppender) + */ + virtual QDebug debug(QDebug &rDebug) const; + friend QDebug operator<<(QDebug debug, + const Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + + void forcedLog(Level level, const QString &rMessage) const; + + private: + const QString mName; + LoggerRepository* mpLoggerRepository; + volatile bool mAdditivity; + Level mLevel; + Logger *mpParent; + + // Needs to be friend to create Logger objects + friend class Hierarchy; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates Logger + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * To handle subclassing 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 Logger &rLogger); +#endif // QT_NO_DEBUG_STREAM + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEinfo(Log4Qt::Logger, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGER_H diff --git a/ext/Log4Qt/src/loggerrepository.cpp b/ext/Log4Qt/src/loggerrepository.cpp new file mode 100755 index 0000000..2f19bac --- /dev/null +++ b/ext/Log4Qt/src/loggerrepository.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.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 "loggerrepository.h" + +#include <QtCore/QDebug> + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggerRepository + **************************************************************************/ + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + LoggerRepository::~LoggerRepository() {} + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository) + { + return rLoggerRepository.debug(debug); + } +#endif // QT_NO_DEBUG_STREAM + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/loggerrepository.h b/ext/Log4Qt/src/loggerrepository.h new file mode 100755 index 0000000..b6d42b6 --- /dev/null +++ b/ext/Log4Qt/src/loggerrepository.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggerrepository.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_LOGGERREPOSITORY_H +#define LOG4QT_LOGGERREPOSITORY_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QList> +#include "level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggerRepository is abstract base class for a logger + * repository. + */ + class LOG4QT_EXPORT LoggerRepository + { + public: + // LoggerRepository(); // Use compiler default + // LoggerRepository(const LoggerRepository &rOther); // Use compiler default + + // LoggerRepository &operator=(const LoggerRepository &rOther); // Use compiler default + virtual ~LoggerRepository(); + + public: + virtual bool exists(const QString &rName) const = 0; + virtual Logger *logger(const QString &rName) = 0; + // JAVA: virtual Logger *logger(const String &rName, LoggerFactory *pFactory); + virtual QList<Logger *> loggers() const = 0; + virtual Logger *rootLogger() const = 0; + virtual Level threshold() const = 0; + virtual void setThreshold(Level level) = 0; + virtual void setThreshold(const QString &rThreshold) = 0; + + virtual bool isDisabled(Level level) = 0; + virtual void resetConfiguration() = 0; + virtual void shutdown() = 0; + + // JAVA: virtual void addHierarchyEventListener(HierarchyEventListener *pEventListener); + // JAVA: virtual void emitNoAppenderWarning(Logger *plogger) const; + // JAVA: virtual void fireAddAppenderEvent(Logger *plogger, Appender *pAppender) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + *\relates LoggerRepository + * + * 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 LoggerRepository &rLoggerRepository) + * to generate class specific output. + * + * \sa QDebug operator<<(QDebug debug, const LoggerRepository &rLoggerRepository) + */ + virtual QDebug debug(QDebug &rDebug) const = 0; + friend QDebug operator<<(QDebug debug, + const LoggerRepository &rLoggerRepository); +#endif + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggerRepository + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * To handle subclassing 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 LoggerRepository &rLoggerRepository); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LoggerRepository, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGGERREPOSITORY_H diff --git a/ext/Log4Qt/src/loggingevent.cpp b/ext/Log4Qt/src/loggingevent.cpp new file mode 100644 index 0000000..91602bb --- /dev/null +++ b/ext/Log4Qt/src/loggingevent.cpp @@ -0,0 +1,279 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: loggingevent.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 "loggingevent.h" + +#include <QtCore/QBuffer> +#include <QtCore/QByteArray> +#include <QtCore/QDataStream> +#include <QtCore/QDebug> +#include <QtCore/QMutex> +#include <QtCore/QThread> +#include "helpers/datetime.h" +#include "helpers/initialisationhelper.h" +#include "logger.h" +#include "mdc.h" +#include "ndc.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + LOG4QT_GLOBAL_STATIC(QMutex, sequence_guard) + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: LoggingEvent + **************************************************************************/ + + + LoggingEvent::LoggingEvent() : + QEvent(eventId), + mLevel(Level::NULL_INT), + mpLogger(0), + mMessage(), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage) : + QEvent(eventId), + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(DateTime::currentDateTime().toMilliSeconds()) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp) : + QEvent(eventId), + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(NDC::peek()), + mProperties(MDC::context()), + mSequenceNumber(nextSequenceNumber()), + mThreadName(), + mTimeStamp(timeStamp) + { + setThreadNameToCurrent(); + } + + + LoggingEvent::LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash<QString, QString> &rProperties, + const QString &rThreadName, + qint64 timeStamp) : + QEvent(eventId), + mLevel(level), + mpLogger(pLogger), + mMessage(rMessage), + mNdc(rNdc), + mProperties(rProperties), + mSequenceNumber(nextSequenceNumber()), + mThreadName(rThreadName), + mTimeStamp(timeStamp) + { + } + + + QString LoggingEvent::loggerName() const + { + if (mpLogger) + return mpLogger->name(); + else + return QString(); + } + + + QString LoggingEvent::toString() const + { + return level().toString() + QLatin1Char(':') + message(); + } + + + qint64 LoggingEvent::sequenceCount() + { + QMutexLocker locker(sequence_guard()); + + return msSequenceCount; + } + + + qint64 LoggingEvent::startTime() + { + return InitialisationHelper::startTime(); + } + + + void LoggingEvent::setThreadNameToCurrent() + { + if (QThread::currentThread()) + { + mThreadName = QThread::currentThread()->objectName(); + // if object name is not set use thread function address for thread identification + if (mThreadName.isEmpty()) + mThreadName = QString("0x%1").arg((quintptr)(QThread::currentThread()), QT_POINTER_SIZE * 2, 16, QChar('0')); + } + } + + + qint64 LoggingEvent::nextSequenceNumber() + { + QMutexLocker locker(sequence_guard()); + + return ++msSequenceCount; + } + + qint64 LoggingEvent::msSequenceCount = 0; + const QEvent::Type LoggingEvent::eventId = static_cast<QEvent::Type>(QEvent::registerEventType()); + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DATASTREAM + QDataStream &operator<<(QDataStream &rStream, const LoggingEvent &rLoggingEvent) + { + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + QDataStream stream(&buffer); + + // version + quint16 version = 0; + stream << version; + // version 0 data + stream << rLoggingEvent.mLevel + << rLoggingEvent.loggerName() + << rLoggingEvent.mMessage + << rLoggingEvent.mNdc + << rLoggingEvent.mProperties + << rLoggingEvent.mSequenceNumber + << rLoggingEvent.mThreadName + << rLoggingEvent.mTimeStamp; + + buffer.close(); + rStream << buffer.buffer(); + return rStream; + } + + + QDataStream &operator>>(QDataStream &rStream, LoggingEvent &rLoggingEvent) + { + QByteArray array; + rStream >> array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadOnly); + QDataStream stream(&buffer); + + // version + quint16 version; + stream >> version; + // Version 0 data + QString logger; + stream >> rLoggingEvent.mLevel + >> logger + >> rLoggingEvent.mMessage + >> rLoggingEvent.mNdc + >> rLoggingEvent.mProperties + >> rLoggingEvent.mSequenceNumber + >> rLoggingEvent.mThreadName + >> rLoggingEvent.mTimeStamp; + if (logger.isEmpty()) + rLoggingEvent.mpLogger = 0; + else + rLoggingEvent.mpLogger = Logger::logger(logger); + + buffer.close(); + return rStream; + } +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent) + { + QString logger; + if (rLoggingEvent.logger() != 0) + logger = rLoggingEvent.logger()->name(); + + debug.nospace() << "LoggingEvent(" + << "level:" << rLoggingEvent.level().toString() << " " + << "logger:" << logger << " " + << "message:" << rLoggingEvent.message() << " " + << "sequencenumber:" << rLoggingEvent.sequenceNumber() << " " + << "threadname:" << rLoggingEvent.threadName() << " " + << "timestamp:" << rLoggingEvent.timeStamp() + << "(" << DateTime::fromMilliSeconds(rLoggingEvent.timeStamp()) << ")" + << "sequenceCount:" << rLoggingEvent.sequenceCount() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/loggingevent.h b/ext/Log4Qt/src/loggingevent.h new file mode 100644 index 0000000..d06c842 --- /dev/null +++ b/ext/Log4Qt/src/loggingevent.h @@ -0,0 +1,223 @@ +/****************************************************************************** +* +* package: Log4Qt +* file: loggingevent.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_LOG4QTEVENT_H +#define LOG4QT_LOG4QTEVENT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QDateTime> +#include <QtCore/QHash> +#include <QtCore/QMetaType> +#include <QtCore/QStringList> +#include <QtCore/QEvent> +#include "level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class Logger; + + /*! + * \brief The class LoggingEvent is the internal representation of a + * logging event. + * + * The class uses milliseconds since 1970-01-01T00:00:00, Coordinated + * Universal Time for time values. For converstion from and to QDateTime + * use DateTime. + */ + class LOG4QT_EXPORT LoggingEvent : public QEvent + { + public: + static const QEvent::Type eventId; + LoggingEvent(); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + qint64 timeStamp); + LoggingEvent(const Logger *pLogger, + Level level, + const QString &rMessage, + const QString &rNdc, + const QHash<QString, QString> &rProperties, + const QString &rThreadName, + qint64 timeStamp); + // LoggingEvent(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + // virtual ~LoggingEvent(); // Use compiler default + // LoggingEvent &operator=(const LoggingEvent &LoggingEvent::rOther); // Use compiler default + + // JAVA: QString fqnOfLoggerClass() const; + Level level() const; + // LocationInformation locationInformation() const; + const Logger *logger() const; + QString message() const; + QHash<QString, QString> mdc() const; + QString ndc() const; + QHash<QString, QString> properties() const; + qint64 sequenceNumber() const; + QString threadName() const; + // JAVA: ThrowableInformation throwableInformation() const; + qint64 timeStamp() const; + + // JAVA: bool locationInformationExists() const; + QString loggerName() const; + QString property(const QString &rKey) const; + QStringList propertyKeys() const; + void setProperty(const QString &rKey, const QString &rValue); + // JAVA: QString throwableStrRep() const; + QString toString() const; + static qint64 sequenceCount(); + static qint64 startTime(); + + private: + void setThreadNameToCurrent(); + static qint64 nextSequenceNumber(); + + private: + Level mLevel; + const Logger *mpLogger; + QString mMessage; + QString mNdc; + QHash<QString, QString> mProperties; + qint64 mSequenceNumber; + QString mThreadName; + qint64 mTimeStamp; + static qint64 msSequenceCount; + +#ifndef QT_NO_DATASTREAM + // Needs to be friend to stream objects + friend QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + friend QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DATASTREAM + /*! + * \relates LoggingEvent + * + * Writes the given error \a rLoggingEvent to the given stream \a rStream, + * and returns a reference to the stream. + */ + QDataStream &operator<<(QDataStream &rStream, + const LoggingEvent &rLoggingEvent); + + /*! + * \relates LoggingEvent + * + * Reads an error from the given stream \a rStream into the given + * error \a rLoggingEvent, and returns a reference to the stream. + */ + QDataStream &operator>>(QDataStream &rStream, + LoggingEvent &rLoggingEvent); +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LoggingEvent + * + * Writes all object member variables to the given debug stream \a debug and + * returns the stream. + * + * <tt> + * %LoggingEvent(level:"WARN" logger:"Log4Qt::Properties" + * message:"Unknown escape sequence '\j' in property starting at line 1" + * sequencenumber:14 threadname:"main" + * timestamp:1194337148937(QDateTime("Tue Nov 6 03:19:08 2007") ) + * sequenceCount: 14 ) + * </tt> + * + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LoggingEvent &rLoggingEvent); +#endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Level LoggingEvent::level() const + { return mLevel; } + + inline const Logger *LoggingEvent::logger() const + { return mpLogger; } + + inline QString LoggingEvent::message() const + { return mMessage; } + + inline QHash<QString, QString> LoggingEvent::mdc() const + { return mProperties; } + + inline QString LoggingEvent::ndc() const + { return mNdc; } + + inline QHash<QString, QString> LoggingEvent::properties() const + { return mProperties; } + + inline qint64 LoggingEvent::sequenceNumber() const + { return mSequenceNumber; } + + inline QString LoggingEvent::threadName() const + { return mThreadName; } + + inline qint64 LoggingEvent::timeStamp() const + { return mTimeStamp; } + + inline QString LoggingEvent::property(const QString &rKey) const + { return mProperties.value(rKey); } + + inline QStringList LoggingEvent::propertyKeys() const + { return QStringList(mProperties.keys()); } + + inline void LoggingEvent::setProperty(const QString &rKey, const QString &rValue) + { mProperties.insert(rKey, rValue); } + + +} // namespace Log4Qt + + +Q_DECLARE_METATYPE(Log4Qt::LoggingEvent) +Q_DECLARE_TYPEINFO(Log4Qt::LoggingEvent, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_LOG4QTEVENT_H diff --git a/ext/Log4Qt/src/logmanager.cpp b/ext/Log4Qt/src/logmanager.cpp new file mode 100755 index 0000000..5d47c6f --- /dev/null +++ b/ext/Log4Qt/src/logmanager.cpp @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes: Sep 2008, Martin Heinrich: + * - Resolved compilation problem with Microsoft Visual Studio 2005 + * 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 "logmanager.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QMutex> +#include <QtCore/QSettings> +#include <QtCore/QStringList> +#include "consoleappender.h" +#include "helpers/datetime.h" +#include "helpers/initialisationhelper.h" +#include "helpers/optionconverter.h" +#include "hierarchy.h" +#include "propertyconfigurator.h" +#include "ttcclayout.h" +#include "varia/denyallfilter.h" +#include "varia/levelrangefilter.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager) + LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard) + + + + /************************************************************************** + * Class implementation: LogManager + **************************************************************************/ + + + LogManager::LogManager() : + mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger() + mpLoggerRepository(new Hierarchy()), + mHandleQtMessages(false), + mOldQtMsgHandler(0) + { + } + + + LogManager::~LogManager() + { + static_logger()->warn("Unexpected destruction of LogManager"); + + // doSetConfigureHandleQtMessages(false); + // delete mpLoggerRepository; + } + + + Logger *LogManager::rootLogger() + { + return instance()->mpLoggerRepository->rootLogger(); + } + + + QList<Logger*> LogManager::loggers() + { + return instance()->mpLoggerRepository->loggers(); + } + + + Level LogManager::threshold() + { + return instance()->mpLoggerRepository->threshold(); + } + + + void LogManager::setThreshold(Level level) + { + instance()->mpLoggerRepository->setThreshold(level); + } + + + bool LogManager::exists(const char *pName) + { + return instance()->mpLoggerRepository->exists(QLatin1String(pName)); + } + + + LogManager *LogManager::instance() + { + // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive + // to construct, an exit handler must be set and doStartup must be + // called. + + if (!mspInstance) + { + QMutexLocker locker(singleton_guard()); + if (!mspInstance) + { + mspInstance = new LogManager; + // qAddPostRoutine(shutdown); + atexit(shutdown); + mspInstance->doConfigureLogLogger(); + mspInstance->welcome(); + mspInstance->doStartup(); + } + } + return mspInstance; + } + + + Logger *LogManager::logger(const QString &rName) + { + return instance()->mpLoggerRepository->logger(rName); + } + + + void LogManager::resetConfiguration() + { + setHandleQtMessages(false); + instance()->mpLoggerRepository->resetConfiguration(); + configureLogLogger(); + } + + + const char* LogManager::version() + { + return LOG4QT_VERSION_STR; + } + + + void LogManager::shutdown() + { + instance()->mpLoggerRepository->shutdown(); + } + + + void LogManager::doSetHandleQtMessages(bool handleQtMessages) + { + QMutexLocker locker(&mObjectGuard); + + if (instance()->mHandleQtMessages == handleQtMessages) + return; + + instance()->mHandleQtMessages = handleQtMessages; + if (instance()->mHandleQtMessages) + { + static_logger()->trace("Activate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler); +#else + instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler); +#endif + + } + else + { + static_logger()->trace("Deactivate Qt message handling"); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + qInstallMsgHandler(instance()->mOldQtMsgHandler); +#else + qInstallMessageHandler(instance()->mOldQtMsgHandler); +#endif + } + } + + + void LogManager::doConfigureLogLogger() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Level + QString value = InitialisationHelper::setting(QLatin1String("Debug"), + QLatin1String("ERROR")); + logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT)); + + // Common layout + TTCCLayout *p_layout = new TTCCLayout(); + p_layout->setName(QLatin1String("LogLog TTCC")); + p_layout->setContextPrinting(false); + p_layout->activateOptions(); + + // Common deny all filter + Filter *p_denyall = new DenyAllFilter(); + p_denyall->activateOptions(); + + // ConsoleAppender on stdout for all events <= INFO + ConsoleAppender *p_appender; + LevelRangeFilter *p_filter; + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::NULL_INT); + p_filter->setLevelMax(Level::INFO_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stdout")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + + // ConsoleAppender on stderr for all events >= WARN + p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET); + p_filter = new LevelRangeFilter(); + p_filter->setNext(p_denyall); + p_filter->setLevelMin(Level::WARN_INT); + p_filter->setLevelMax(Level::OFF_INT); + p_filter->activateOptions(); + p_appender->setName(QLatin1String("LogLog stderr")); + p_appender->addFilter(p_filter); + p_appender->activateOptions(); + logLogger()->addAppender(p_appender); + } + + + void LogManager::doStartup() + { + QMutexLocker locker(&instance()->mObjectGuard); + + // Override + QString default_value = QLatin1String("false"); + QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"), + default_value); + if (value != default_value) + { + static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation"); + return; + } + + // Configuration using setting Configuration + value = InitialisationHelper::setting(QLatin1String("Configuration")); + if (QFile::exists(value)) + { + static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value); + PropertyConfigurator::configure(value); + return; + } + + // Configuration using setting + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + QSettings s; + s.beginGroup(log4qt_group); + if (s.childGroups().contains(properties_group)) + { + const QString group(QLatin1String("Properties")); + static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group); + s.beginGroup(properties_group); + PropertyConfigurator::configure(s); + return; + } + } + + // Configuration using default file + const QString default_file(QLatin1String("log4qt.properties")); + if (QFile::exists(default_file)) + { + static_logger()->debug("Default initialisation configures from default file '%1'", default_file); + PropertyConfigurator::configure(default_file); + return; + } + + static_logger()->debug("Default initialisation leaves package unconfigured"); + } + + + void LogManager::welcome() + { + static_logger()->info("Initialising Log4Qt %1", + QLatin1String(LOG4QT_VERSION_STR)); + + // Debug: Info + if (static_logger()->isDebugEnabled()) + { + // Create a nice timestamp with UTC offset + DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime()); + QString offset; + { + QDateTime utc = start_time.toUTC(); + QDateTime local = start_time.toLocalTime(); + QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC); + int min = utc.secsTo(local_as_utc) / 60; + if (min < 0) + offset += QLatin1Char('-'); + else + offset += QLatin1Char('+'); + min = abs(min); + offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0')); + offset += QLatin1Char(':'); + offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0')); + } + static_logger()->debug("Program startup time is %1 (UTC%2)", + start_time.toString(QLatin1String("ISO8601")), + offset); + static_logger()->debug("Internal logging uses the level %1", + logLogger()->level().toString()); + } + + // Trace: Dump settings + if (static_logger()->isTraceEnabled()) + { + static_logger()->trace("Settings from the system environment:"); + QString entry; + Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys()) + static_logger()->trace(" %1: '%2'", + entry, + InitialisationHelper::environmentSettings().value(entry)); + + static_logger()->trace("Settings from the application settings:"); + if (QCoreApplication::instance()) + { + const QLatin1String log4qt_group("Log4Qt"); + const QLatin1String properties_group("Properties"); + static_logger()->trace(" %1:", log4qt_group); + QSettings s; + s.beginGroup(log4qt_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + static_logger()->trace(" %1/%2:", log4qt_group, properties_group); + s.beginGroup(properties_group); + Q_FOREACH (entry, s.childKeys()) + static_logger()->trace(" %1: '%2'", + entry, + s.value(entry).toString()); + } else + static_logger()->trace(" QCoreApplication::instance() is not available"); + } + } + + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage) + { +#else + void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & pMessage) + { +#endif + Level level; + switch (type) + { + case QtDebugMsg: + level = Level::DEBUG_INT; + break; + case QtWarningMsg: + level = Level::WARN_INT; + break; + case QtCriticalMsg: + level = Level::ERROR_INT; + break; + case QtFatalMsg: + level = Level::FATAL_INT; + break; + default: + level = Level::TRACE_INT; + } + instance()->qtLogger()->log(level, pMessage); + + // Qt fatal behaviour copied from global.cpp qt_message_output() + // begin { + + if ((type == QtFatalMsg) || + ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) ) + { +#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) + // get the current report mode + int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); + _CrtSetReportMode(_CRT_ERROR, reportMode); + int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage); + if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW) + return; // ignore + else if (ret == 1) + _CrtDbgBreak(); +#endif + +#if defined(Q_OS_UNIX) && defined(QT_DEBUG) + abort(); // trap; generates core dump +#else + exit(1); // goodbye cruel world +#endif + } + + // } end + } + + + LogManager *LogManager::mspInstance = 0; + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const LogManager &rLogManager) + { + Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008 + QList<Logger *> loggers = rLogManager.loggers(); + debug.nospace() << "LogManager(" + << "loggerrepository:" << *rLogManager.loggerRepository() + << "log-level:" << rLogManager.logLogger()->level().toString() + << "log-appenders:" << rLogManager.logLogger()->appenders().count() + << "qt-level:" << rLogManager.qtLogger()->level().toString() + << "qt-appenders:" << rLogManager.qtLogger()->appenders().count() + << "handleqtmessages:" << rLogManager.handleQtMessages() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/logmanager.h b/ext/Log4Qt/src/logmanager.h new file mode 100755 index 0000000..641f658 --- /dev/null +++ b/ext/Log4Qt/src/logmanager.h @@ -0,0 +1,337 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logmanager.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_LOGMANAGER_H +#define LOG4QT_LOGMANAGER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QObject> + +#include <QtCore/QHash> +#include <QtCore/QList> +#include <QtCore/QMutex> +#include <QtCore/QString> +#include "level.h" +#include "logger.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggerRepository; + + /*! + * \brief The class LogManager manages Logger in the default + * LoggerRepository. + * + * The LogManager manages logger in a single Hierarchy instance. It + * provides access to special logger over the logLogger(), qtLogger() + * and rootLogger() member functions. + * + * The LogManager is handling the initialisation on startup. The + * initialisation procedure will first attempt to configure the package + * based on environment variables. If the attempt fails it will check for + * the existence of configuration files in several location. For detailed + * description of the initialisation procedure see \ref Init + * "Initialization procedure". + * + * Messages created by qDebug(), qWarning(), qCritical() and qFatal() can + * be can be handled by the LogManager. By default the message handling + * is disabled. It can be enabled by calling setHandleQtMessages(). Once + * enabled all messages are logged using the logger qtLogger(). + * + * The Log4Qt runtime version is accessible over version(). The macros + * \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION" and + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" provide the + * compile time version. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT LogManager + { + private: + LogManager(); + LogManager(const LogManager &rOther); // Not implemented + virtual ~LogManager(); + LogManager &operator=(const LogManager &rOther); // Not implemented + + public: + /*! + * Returns if the handling of messages created by calls to qDebug(), + * qWarning(), qCritical() and qFatal() is activated. + * + * \sa setHandleQtMessages() + */ + static bool handleQtMessages(); + + static LoggerRepository *loggerRepository(); + + /*! + * Returns the logger used for logging internal messages. See + * \ref LogLog "Logging within the package" for more details. + * + * Calling this function is equivalent to calling logger("Log4Qt"). + */ + static Logger *logLogger(); + + /*! + * Returns a pointer to the logger used for logging messages created by + * calls to qDebug(), qWarning(), qCritical() and qFatal(). + * + * Calling this function is equivalent to calling logger("Qt"). + * + * \sa setHandleQtMessages() + */ + static Logger *qtLogger(); + + static Logger *rootLogger(); + static QList<Logger*> loggers(); + static Level threshold(); + static void setThreshold(Level level); + + /*! + * Activates or deactivates the handling of messages created by calls + * to qDebug(), qWarning(), qCritical() and qFatal() is activated. + * + * If activated, a Qt message handler is installed. Messages are logged + * using the logger returned by qtLogger(). For fatal messages the same + * exit procedure is implemented as for qFatal(). + * + * The following mappping is used from QtMsgType to Level: + * + * <table align="center" border="1" cellpadding="2" cellspacing="0" bordercolor="#84b0c7"> + * <tr bgcolor="#d5e1e8"> + * <th> QtMsgType </th> + * <th> %Level </th> + * </tr><tr> + * <td> QtDebugMsg </td> + * <td> Level::DEBUG_INT </td> + * </tr><tr bgcolor="#ffffff"> + * <td> QtWarningMsg </td> + * <td> Level::WARN_INT </td> + * </tr><tr> + * <td> QtCriticalMsg </td> + * <td> Level::ERROR_INT </td> + * </tr><tr bgcolor="#ffffff"> + * <td> QtFatalMsg </td> + * <td> Level::FATAL_INT </td> + * </tr><tr> + * <td> QtSystemMsg </td> + * <td> Level::TRACE_INT </td> + * </tr> + * </table> + * + * The default value is false for not handling Qt messages. + * + * \sa handleQtMessages(), qInstallMsgHandler(), qFatal() + */ + static void setHandleQtMessages(bool handleQtMessages); + + /*! + * Configures the logging for the package to its default behaviour. + * + * The logger logLogger() is configured to be not additive. Messages + * with the level Level::ERROR_INT and Level::FATAL_INT are written + * to \c stderr using a ConsoleAppender. The remaining messages are + * written to \c stdout using a second ConsoleAppender. The level is + * read from the system environment or application settings using + * InitialisationHelper::setting() with the key \c Debug. If a level + * value is found, but it is not a valid Level string, + * Level::DEBUG_INT is used. If no level string is found + * Level::ERROR_INT is used. + * + * The function does not remove any appender from the logger + * logLogger(). + * + * \sa \ref LogLog "Logging within the package", + * \ref Env "Environment Variables", + * resetConfiguration(), InitialisationHelper::setting() + */ + static void configureLogLogger(); + + static bool exists(const char *pName); + // JAVA: void fireAddAppenderEvent(Logger *pLogger, Appender *pAppender); + + /*! + * Returns the LogManager instance. + */ + static LogManager *instance(); + + static Logger *logger(const QString &rName); + + /*! + * Reset all values contained in logger repository to their default. + * + * All appenders are removed from all loggers. The loggers are handled + * in no particular order. The last loggers to be reset are qtLogger(), + * logLogger() and rootLogger() in that order. + * + * The handling of messages created by calls to qDebug(), qWarning(), + * qCritical() and qFatal() is deactivated. + * + * The internal logging is initialised to its default bahaviour + * using configureLogLogger(). + * + * \sa LoggerRepository::resetConfiguration(), setHandleQtMessages(), + * configureLogLogger() + */ + static void resetConfiguration(); + + static void shutdown(); + + /*! + * Executes the default initialisation procedure of the package. + * + * The function will test for the setting \c DefaultInitOverride in + * the system environment and application settings using + * \ref InitialisationHelper::setting(). If the value is present and + * set to anything else then \c false, the initialisation is aborted. + * <br> + * The system environment and application settings are tested for the + * setting \c Configuration. If it is found and it is a valid path to + * a file, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". If the setting + * \c Configuration is not available and a QCoreApplication object is + * present, the application settings are tested for a group + * \c Properties. If the group exists, the package is configured + * with the setting using the + * \ref PropertyConfigurator::doConfigure(const QSettings &r, LoggerRepository *) + * "PropertyConfiguratordoConfigure()". If neither a configuration + * file nor configuration settings could be found, the current working + * directory is searched for the file \c "log4qt.properties". If it is + * found, the package is configured with the file using + * \ref PropertyConfigurator::doConfigure(const QString &, LoggerRepository *) + * "PropertyConfigurator::doConfigure()". + * + * \sa \ref Init "Initialization procedure", + * \ref Env "Environment Variables", + * InitialisationHelper::setting() + */ + static void startup(); + + /*! + * Returns the version number of Log4Qt at run-time. This may be a + * different version than the version the application was compiled + * against. + * + * \sa \ref Log4Qt::LOG4QT_VERSION "LOG4QT_VERSION", + * \ref Log4Qt::LOG4QT_VERSION_STR "LOG4QT_VERSION_STR" + + */ + static const char* version(); + + private: + void doSetHandleQtMessages(bool handleQtMessages); + void doConfigureLogLogger(); + void doStartup(); + void welcome(); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + static void qtMessageHandler(QtMsgType type, + const char *pMessage); +#else + static void qtMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & pMessage); +#endif + + private: + mutable QMutex mObjectGuard; + LoggerRepository *mpLoggerRepository; + Logger *mpNullLogger; + bool mHandleQtMessages; +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QtMsgHandler mOldQtMsgHandler; +#else + QtMessageHandler mOldQtMsgHandler; +#endif + static LogManager *mspInstance; + }; + + + /*************************************************************************** + * Operators, Helper + ***************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates LogManager + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * <tt> + * %LogManager(loggerrepository:Hierarchy(loggers:6 root-level:"DEBUG" + * root-appenders:0 log-level: "NULL" log-appenders:0 + * qt-level: "NULL" qt-appenders:0 handleqtmessages: false ) + * </tt> + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const LogManager &rLogManager); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline LoggerRepository *LogManager::loggerRepository() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return instance()->mpLoggerRepository; } + + inline bool LogManager::handleQtMessages() + { // QMutexLocker locker(&instance()->mObjectGuard); // Read/Write of bool is safe + return instance()->mHandleQtMessages; } + + inline Logger *LogManager::logLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Log4Qt")); } + + inline Logger *LogManager::qtLogger() + { // QMutexLocker locker(&instance()->mObjectGuard); // Constant for object lifetime + return logger(QLatin1String("Qt")); } + + inline void LogManager::setHandleQtMessages(bool handleQtMessages) + { instance()->doSetHandleQtMessages(handleQtMessages); } + + inline void LogManager::configureLogLogger() + { instance()->doConfigureLogLogger(); } + + inline void LogManager::startup() + { instance()->doStartup(); } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LogManager, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LOGMANAGER_H diff --git a/ext/Log4Qt/src/logstream.cpp b/ext/Log4Qt/src/logstream.cpp new file mode 100644 index 0000000..ed62660 --- /dev/null +++ b/ext/Log4Qt/src/logstream.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logstream.h + * created: March, 2011 + * author: Tim Besard + * + * + * Copyright 2011 Tim Besard + * + * 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 "logstream.h" +#include "logger.h" + + +namespace Log4Qt { + + /************************************************************************** + * Class implementation: Logger + **************************************************************************/ + + LogStream::~LogStream() + { + if (!--stream->ref) { + switch (mLevel.toInt()) + { + case Level::TRACE_INT: + mLogger.trace(stream->buffer); + break; + case Level::DEBUG_INT: + mLogger.debug(stream->buffer); + break; + case Level::INFO_INT: + mLogger.info(stream->buffer); + break; + case Level::WARN_INT: + mLogger.warn(stream->buffer); + break; + case Level::ERROR_INT: + mLogger.error(stream->buffer); + break; + case Level::FATAL_INT: + mLogger.fatal(stream->buffer); + break; + } + delete stream; + } + } +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/logstream.h b/ext/Log4Qt/src/logstream.h new file mode 100644 index 0000000..a0e355c --- /dev/null +++ b/ext/Log4Qt/src/logstream.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: logstream.h + * created: March, 2011 + * author: Tim Besard + * + * + * Copyright 2011 Tim Besard + * + * 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_LOGSTREAM_H +#define LOG4QT_LOGSTREAM_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QTextStream> +#include <QtCore/QString> +#include "level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + class Logger; + + class LOG4QT_EXPORT LogStream + { + + private: + struct Stream { + Stream() : ts(&buffer, QIODevice::WriteOnly), ref(1) {} + QTextStream ts; + QString buffer; + int ref; + } *stream; + + public: + inline LogStream(const Logger& iLogger, Level iLevel) : stream(new Stream()), mLogger(iLogger), mLevel(iLevel) + { + } + inline LogStream(const LogStream &o):stream(o.stream),mLogger(o.mLogger),mLevel(o.mLevel) + { + ++stream->ref; + } + ~LogStream(); + + inline LogStream &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return *this; } +#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) + inline LogStream &operator<<(QBool t) { stream->ts << (bool(t != 0) ? "true" : "false"); return *this; } +#endif + inline LogStream &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return *this; } + inline LogStream &operator<<(char t) { stream->ts << t; return *this; } + inline LogStream &operator<<(signed short t) { stream->ts << t; return *this; } + inline LogStream &operator<<(unsigned short t) { stream->ts << t; return *this; } + inline LogStream &operator<<(signed int t) { stream->ts << t; return *this; } + inline LogStream &operator<<(unsigned int t) { stream->ts << t; return *this; } + inline LogStream &operator<<(signed long t) { stream->ts << t; return *this; } + inline LogStream &operator<<(unsigned long t) { stream->ts << t; return *this; } + inline LogStream &operator<<(qint64 t) { stream->ts << QString::number(t); return *this; } + inline LogStream &operator<<(quint64 t) { stream->ts << QString::number(t); return *this; } + inline LogStream &operator<<(float t) { stream->ts << t; return *this; } + inline LogStream &operator<<(double t) { stream->ts << t; return *this; } + inline LogStream &operator<<(const char* t) { stream->ts << QString::fromLatin1(t); return *this; } + inline LogStream &operator<<(const QString & t) { stream->ts << t ; return *this; } + inline LogStream &operator<<(const QStringRef & t) { return operator<<(t.toString()); } + inline LogStream &operator<<(const QLatin1String &t) { stream->ts << t.latin1(); return *this; } + inline LogStream &operator<<(const QByteArray & t) { stream->ts << t; return *this; } + inline LogStream &operator<<(const void * t) { stream->ts << t; return *this; } + inline LogStream &operator<<(QTextStreamFunction f) { stream->ts << f; return *this; } + inline LogStream &operator<<(QTextStreamManipulator m) { stream->ts << m; return *this; } + + private: + const Logger& mLogger; + Level mLevel; + }; +} + +#endif // LOG4QT_LOGSTREAM_H diff --git a/ext/Log4Qt/src/mainthreadappender.cpp b/ext/Log4Qt/src/mainthreadappender.cpp new file mode 100644 index 0000000..5417aa7 --- /dev/null +++ b/ext/Log4Qt/src/mainthreadappender.cpp @@ -0,0 +1,125 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mainthreadappender.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. + * + ******************************************************************************/ + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "mainthreadappender.h" +#include "loggingevent.h" +#include "helpers/dispatcher.h" + +#include <QtCore/QDebug> +#include <QtCore/QCoreApplication> +#include <QtCore/QReadLocker> + +namespace Log4Qt +{ + +/************************************************************************** + * Declarations + **************************************************************************/ + + +/************************************************************************** + * C helper functions + **************************************************************************/ + + +/************************************************************************** + * Class implementation: MainThreadAppender + **************************************************************************/ + + +MainThreadAppender::MainThreadAppender(QObject *parent) : AppenderSkeleton(parent) +{} + +MainThreadAppender::~MainThreadAppender() +{ + close(); +} + +bool MainThreadAppender::requiresLayout() const +{ + return false; +} + +void MainThreadAppender::activateOptions() +{ +} + +void MainThreadAppender::close() +{ +} + +void MainThreadAppender::append(const LoggingEvent &rEvent) +{ + QReadLocker locker(&mAppenderGuard); + + Appender *pAppender; + Q_FOREACH(pAppender, mAppenders) + { + if (QThread::currentThread() != qApp->thread()) + { + LoggingEvent *event = new LoggingEvent(rEvent); + qApp->postEvent(pAppender, event); + + } + else + pAppender->doAppend(rEvent); + } +} + +bool MainThreadAppender::checkEntryConditions() const +{ + return AppenderSkeleton::checkEntryConditions(); +} + +#ifndef QT_NO_DEBUG_STREAM +/*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %MainThreadAppender(name:"WA" ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ +QDebug MainThreadAppender::debug(QDebug &rDebug) const +{ + rDebug.nospace() << "MainThreadAppender(" + << "name:" << name() << " " + << ")"; + + return rDebug.space(); +} +#endif // QT_NO_DEBUG_STREAM + + +/************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + +} // namespace Log4Qt + diff --git a/ext/Log4Qt/src/mainthreadappender.h b/ext/Log4Qt/src/mainthreadappender.h new file mode 100644 index 0000000..1e26955 --- /dev/null +++ b/ext/Log4Qt/src/mainthreadappender.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mainthreadappender.h + * created: Febrary 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 LOG4QT_MAINTHREADAPPENDER_H +#define LOG4QT_MAINTHREADAPPENDER_H + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" +#include "helpers/appenderattachable.h" + +#include <QtCore/QQueue> +#include <QtCore/QMutex> + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + +/*! + * \brief The class MainThreadAppender uses the QEvent system to write + * log from not main threads within the main thread. + * + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ +class LOG4QT_EXPORT MainThreadAppender : public AppenderSkeleton, public AppenderAttachable +{ +Q_OBJECT + +public: + MainThreadAppender(QObject *parent = 0); + virtual ~MainThreadAppender(); + + virtual bool requiresLayout() const; + + virtual void activateOptions(); + virtual void close(); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - none + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + +protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %MainThreadAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + +private: + Q_DISABLE_COPY(MainThreadAppender) + +}; + + +/************************************************************************** + * Operators, Helper + **************************************************************************/ + + +/************************************************************************** + * Inline + **************************************************************************/ + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::MainThreadAppender, Q_COMPLEX_TYPE); // Use default + + +#endif diff --git a/ext/Log4Qt/src/mdc.cpp b/ext/Log4Qt/src/mdc.cpp new file mode 100755 index 0000000..3a1e26d --- /dev/null +++ b/ext/Log4Qt/src/mdc.cpp @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed 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 "mdc.h" + +#include <QtCore/QDebug> +#include <QtCore/QMutex> +#include <QtCore/QThread> +#include "helpers/initialisationhelper.h" +#include "logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: MDC + **************************************************************************/ + + + QString MDC::get(const QString &rKey) + { + if (!instance()->mHash.hasLocalData()) + return QString(); + + return instance()->mHash.localData()->value(rKey); + } + + + QHash<QString, QString> MDC::context() + { + if (!instance()->mHash.hasLocalData()) + return QHash<QString, QString>(); + + return *instance()->mHash.localData(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(MDC) + + + QHash<QString, QString> *MDC::localData() + { + if (!instance()->mHash.hasLocalData()) + instance()->mHash.setLocalData(new QHash<QString, QString>); + return instance()->mHash.localData(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const MDC &rMDC) + { + Q_UNUSED(rMDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "MDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "context:" << rMDC.context() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/mdc.h b/ext/Log4Qt/src/mdc.h new file mode 100755 index 0000000..f4d7abc --- /dev/null +++ b/ext/Log4Qt/src/mdc.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: mdc.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_MDC_H +#define LOG4QT_MDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QString> +#include <QtCore/QHash> +#include <QtCore/QThreadStorage> +#include "log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + +/*! + * \brief The class MDC implements a mapped diagnostic context. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT MDC + { + private: + MDC(); + MDC(const MDC &rOther); // Not implemented + // virtual ~MDC(); // Use compiler default + MDC &operator=(const MDC &rOther); // Not implemented + + public: + static QString get(const QString &rKey); + static QHash<QString, QString> context(); + + /*! + * Returns the MDC instance. + */ + static MDC *instance(); + + static void put(const QString &rKey, const QString &rValue); + static void remove(const QString &rKey); + + private: + static QHash<QString, QString> *localData(); + + private: + QThreadStorage< QHash<QString, QString> * > mHash; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates MDC + * + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %MDC(thread:"main" context:QHash(("login", "Peter")("database", "UAT")) ) + * </tt> + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const MDC &rMDC); + #endif // QT_NO_DEBUG_STREAM + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline MDC::MDC() : + mHash() + {} + + inline void MDC::put(const QString &rKey, const QString &rValue) + { localData()->insert(rKey, rValue); } + + inline void MDC::remove(const QString &rKey) + { localData()->remove(rKey); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::MDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_MDC_H diff --git a/ext/Log4Qt/src/ndc.cpp b/ext/Log4Qt/src/ndc.cpp new file mode 100755 index 0000000..4995a60 --- /dev/null +++ b/ext/Log4Qt/src/ndc.cpp @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.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 "ndc.h" + +#include <QtCore/QDebug> +#include <QtCore/QMutex> +#include <QtCore/QThread> +#include "helpers/initialisationhelper.h" +#include "logger.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt:NDC) + + + + /************************************************************************** + * Class implementation: NDC + **************************************************************************/ + + + void NDC::clear() + { + if (!instance()->mStack.hasLocalData()) + return; + + instance()->mStack.localData()->clear(); + } + + + int NDC::depth() + { + if (!instance()->mStack.hasLocalData()) + return 0; + + return instance()->mStack.localData()->count(); + } + + + LOG4QT_IMPLEMENT_INSTANCE(NDC) + + + QString NDC::pop() + { + if (!instance()->mStack.hasLocalData() || instance()->mStack.localData()->isEmpty()) + { + logger()->warn("Requesting pop from empty NDC stack"); + return QString(); + } + + return instance()->mStack.localData()->pop(); + } + + + void NDC::push(const QString &rMessage) + { + if (!instance()->mStack.hasLocalData()) + instance()->mStack.setLocalData(new QStack<QString>); + + instance()->mStack.localData()->push(rMessage); + } + + + void NDC::setMaxDepth(int maxDepth) + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->size() <= maxDepth) + return; + + instance()->mStack.localData()->resize(maxDepth); + } + + + QString NDC::peek() + { + if (!instance()->mStack.hasLocalData() || + instance()->mStack.localData()->isEmpty()) + return QString(); + + return instance()->mStack.localData()->top(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const NDC &rNDC) + { + Q_UNUSED(rNDC); // To avoid warning C4100 on VS 2008 + debug.nospace() << "NDC(" + << "thread:" << QThread::currentThread()->objectName() << " " + << "peek:" << rNDC.peek() << " " + << "depth:" << rNDC.depth() + << ")"; + return debug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/ndc.h b/ext/Log4Qt/src/ndc.h new file mode 100755 index 0000000..74585c7 --- /dev/null +++ b/ext/Log4Qt/src/ndc.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ndc.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_NDC_H +#define LOG4QT_NDC_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include <QtCore/QString> +#include <QtCore/QStack> +#include <QtCore/QThreadStorage> +#include "log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class NDC implements a nested diagnostic context. + * + * The method remove() is not required. QThreadStorage cleans up on thread + * exit. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT NDC + { + private: + NDC(); + NDC(const NDC &rOther); // Not implemented + // virtual ~NDC(); // Use compiler default + NDC &operator=(const NDC &rOther); // Not implemented + + public: + static void clear(); + // JAVA: static QStack<QString> cloneStack(); + // JAVA: static QString get(); + static int depth(); + // JAVA: inherit(Stack stack) + + /*! + * Returns the NDC instance. + */ + static NDC *instance(); + + static QString pop(); + static void push(const QString &rMessage); + // JAVA: static void remove(); // Not required + static void setMaxDepth(int maxDepth); + static QString peek(); + + private: + QThreadStorage< QStack<QString> * > mStack; + }; + + + /****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + #ifndef QT_NO_DEBUG_STREAM + /*! + * \relates NDC + * + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * <tt> + * %NDC(thread:"main" peek:"i = 3" depth:4) + * </tt> + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const NDC &rNDC); + #endif // QT_NO_DEBUG_STREAM + + + /****************************************************************************** + * Inline + ******************************************************************************/ + + inline NDC::NDC() : + mStack() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NDC, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NDC_H diff --git a/ext/Log4Qt/src/patternlayout.cpp b/ext/Log4Qt/src/patternlayout.cpp new file mode 100755 index 0000000..1f3e354 --- /dev/null +++ b/ext/Log4Qt/src/patternlayout.cpp @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.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 "patternlayout.h" + +#include <QtCore/QDebug> +#include "helpers/patternformatter.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: PatternLayout + **************************************************************************/ + + + PatternLayout::PatternLayout(QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(DEFAULT_CONVERSION_PATTERN); + } + + + PatternLayout::PatternLayout(const QString &rPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(rPattern); + } + + + PatternLayout::PatternLayout(ConversionPattern conversionPattern, + QObject *pParent) : + Layout(pParent), + mPattern(), + mpPatternFormatter(0) + { + setConversionPattern(conversionPattern); + } + + + PatternLayout::~PatternLayout() + { + delete mpPatternFormatter; + } + + + void PatternLayout::setConversionPattern(ConversionPattern conversionPattern) + { + switch (conversionPattern) + { + case DEFAULT_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%m%n")); + break; + case TTCC_CONVERSION_PATTERN: + setConversionPattern(QLatin1String("%r [%t] %p %c %x - %m%n")); + break; + default: + Q_ASSERT_X(false, "PatternLayout::setConversionFormat", "Unkown ConversionFormat"); + setConversionPattern(QString()); + } + } + + + QString PatternLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "PatternLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void PatternLayout::updatePatternFormatter() + { + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(mPattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug PatternLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "PatternLayout(" + << "name:" << name() << " " + << "pattern:" << conversionPattern() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/patternlayout.h b/ext/Log4Qt/src/patternlayout.h new file mode 100755 index 0000000..e54b9fa --- /dev/null +++ b/ext/Log4Qt/src/patternlayout.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: patternlayout.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_PATTERNLAYOUT_H +#define LOG4QT_PATTERNLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + class PatternFormatter; + + /*! + * \brief The class PatternLayout outputs a logging event based on a + * pattern string. + \li c{section_count} : logger name with optional parameter section_count. Section count from end of logger name, sections delimiter is "::"; + \li d{format_string} : date with optional parameters in "{}"-brackets which used by QDateTime::toString(); + \li m : message + \li p : level name + \li r : relative date/time to start application + \li t : thread name + \li x : ndc name + \li X : mdc name + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT PatternLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds the conversion pattern used by the appender. + * + * The default is "%m%n". + * + * \sa conversionPattern(), setConversionPattern() + */ + Q_PROPERTY(QString conversionPattern READ conversionPattern WRITE setConversionPattern) + + public: + /*! + * The enum ConversionPattern defines constants for pattern strings. + * + * \sa setConversionPattern(ConversionPattern); + */ + enum ConversionPattern + { + /*! The default conversion pattern string is "%m,%n". */ + DEFAULT_CONVERSION_PATTERN, + /*! + * The ttcc conversion pattern string is + * "%r [%t] %p %c %x - %m%n". + */ + TTCC_CONVERSION_PATTERN + }; + Q_ENUMS(ConversionPattern) + + PatternLayout(QObject *pParent = 0); + PatternLayout(const QString &rPattern, + QObject *pParent = 0); + + /*! + * Creates a PatternLayout with the conversion pattern value specified + * by the \a conversionPattern constant. + */ + PatternLayout(ConversionPattern conversionPattern, + QObject *pParent = 0); + + virtual ~PatternLayout(); + private: + PatternLayout(const PatternLayout &rOther); // Not implemented + PatternLayout &operator=(const PatternLayout &rOther); // Not implemented + + public: + QString conversionPattern() const; + void setConversionPattern(const QString &rPattern); + + /*! + * Sets the conversion pattern to the value specified by the + * \a conversionPattern constant. + */ + void setConversionPattern(ConversionPattern conversionPattern); + + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %PatternLayout(name:"PL" pattern:"%r [%t] %p %c %x - %m%n" + * "referencecount:3") + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + QString mPattern; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QString PatternLayout::conversionPattern() const + { return PatternLayout::mPattern; } + + inline void PatternLayout::setConversionPattern(const QString &rPattern) + { mPattern = rPattern; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::PatternLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PATTERNLAYOUT_H diff --git a/ext/Log4Qt/src/propertyconfigurator.cpp b/ext/Log4Qt/src/propertyconfigurator.cpp new file mode 100755 index 0000000..1fe3860 --- /dev/null +++ b/ext/Log4Qt/src/propertyconfigurator.cpp @@ -0,0 +1,588 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.cpp + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed VS 2008 unreferenced formal parameter warning by using + * Q_UNUSED in operator<<. + * + * + * Copyright 2007 - 2009 Martin Heinrich + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include "propertyconfigurator.h" + +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include "helpers/configuratorhelper.h" +#include "helpers/factory.h" +#include "helpers/optionconverter.h" +#include "helpers/properties.h" +#include "appender.h" +#include "layout.h" +#include "logger.h" +#include "logmanager.h" +#include "loggerrepository.h" +#include "varia/listappender.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + LOG4QT_DECLARE_STATIC_LOGGER(logger, Log4Qt::PropertyConfigurator) + + + + /************************************************************************** + * Class implementation: PropertyConfigurator + **************************************************************************/ + + + bool PropertyConfigurator::doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromProperties(rProperties, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromFile(rConfigFileName, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + startCaptureErrors(); + configureFromSettings(rSettings, pLoggerRepository); + return stopCaptureErrors(); + } + + + bool PropertyConfigurator::configure(const Properties &rProperties) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rProperties); + } + + + bool PropertyConfigurator::configure(const QString &rConfigFilename) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rConfigFilename); + } + + + bool PropertyConfigurator::configure(const QSettings &rSettings) + { + PropertyConfigurator configurator; + return configurator.doConfigure(rSettings); + } + + + bool PropertyConfigurator::configureAndWatch(const QString &rConfigFileName) + { + // Stop an existing watch to avoid a possible concurrent configuration + ConfiguratorHelper::setConfigurationFile(); + if (rConfigFileName.isEmpty()) + return true; + + PropertyConfigurator configurator; + bool result = configurator.doConfigure(rConfigFileName); + ConfiguratorHelper::setConfigurationFile(rConfigFileName, configure); + return result; + } + + + void PropertyConfigurator::configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository) + { + QFile file(rConfigFileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to open property file '%1'"), + CONFIGURATOR_OPENING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + Properties properties; + properties.load(&file); + if (file.error()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to read property file '%1'"), + CONFIGURATOR_READING_FILE_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rConfigFileName; + e.addCausingError(LogError(file.errorString(), file.error())); + logger()->error(e); + return; + } + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + if (!pLoggerRepository) + pLoggerRepository = LogManager::loggerRepository(); + + configureGlobalSettings(rProperties, pLoggerRepository); + configureRootLogger(rProperties, pLoggerRepository); + configureNonRootElements(rProperties, pLoggerRepository); + mAppenderRegistry.clear(); + } + + + void PropertyConfigurator::configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository) + { + Properties properties; + properties.load(rSettings); + configureFromProperties(properties, pLoggerRepository); + } + + + void PropertyConfigurator::configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureGlobalSettings()", "pLoggerRepository must not be null."); + + const QLatin1String key_reset("log4j.reset"); + const QLatin1String key_debug("log4j.Debug"); + const QLatin1String key_config_debug("log4j.configDebug"); + const QLatin1String key_threshold("log4j.threshold"); + const QLatin1String key_handle_qt_messages("log4j.handleQtMessages"); + + // Test each global setting and set it + // - Reset: log4j.reset + // - Debug: log4j.Debug, log4j.configDebug + // - Threshold: log4j.threshold + // - Handle Qt Messages: log4j.handleQtMessages + + // Reset + QString value = rProperties.property(key_reset); + if (!value.isEmpty() && OptionConverter::toBoolean(value, false)) + { + // Use LogManager and not pLoggerRepository to reset internal + // logging. + LogManager::resetConfiguration(); + logger()->debug("Reset configuration"); + } + + // Debug + value = rProperties.property(key_debug); + if (value.isNull()) + { + value = rProperties.property(key_config_debug); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_config_debug, key_debug); + } + if (!value.isNull()) + { + // Don't use OptionConverter::toLevel(). Invalid level string is a valid setting + bool ok; + Level level = Level::fromString(value, &ok); + if (!ok) + level = Level::DEBUG_INT; + LogManager::logLogger()->setLevel(level); + logger()->debug("Set level for Log4Qt logging to %1", + LogManager::logLogger()->level().toString()); + } + + // Threshold + value = rProperties.property(key_threshold); + if (!value.isNull()) + { + pLoggerRepository->setThreshold(OptionConverter::toLevel(value, Level::ALL_INT)); + logger()->debug("Set threshold for LoggerRepository to %1", + pLoggerRepository->threshold().toString()); + } + + // Handle Qt messages + value = rProperties.property(key_handle_qt_messages); + if (!value.isNull()) + { + LogManager::setHandleQtMessages(OptionConverter::toBoolean(value, false)); + logger()->debug("Set handling of Qt messages LoggerRepository to %1", + QVariant(LogManager::handleQtMessages()).toString()); + } + } + + + void PropertyConfigurator::configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureNonRootElements()", "pLoggerRepository must not be null."); + + const QString logger_prefix = QLatin1String("log4j.logger."); + const QString category_prefix = QLatin1String("log4j.category."); + + // Iterate through all entries: + // - Test for the logger/category prefix + // - Convert JAVA class names to C++ ones + // - Parse logger data (Level, Appender) + // - Parse logger additivity + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + QString java_name; + if (key.startsWith(logger_prefix)) + java_name = key.mid(logger_prefix.length()); + else if (key.startsWith(category_prefix)) + java_name = key.mid(category_prefix.length()); + QString cpp_name = OptionConverter::classNameJavaToCpp(java_name); + if (!java_name.isEmpty()) + { + Logger *p_logger = pLoggerRepository->logger(cpp_name); + QString value = OptionConverter::findAndSubst(rProperties, key); + parseLogger(rProperties, p_logger, key, value); + parseAdditivityForLogger(rProperties, p_logger, java_name); + } + } + } + + + void PropertyConfigurator::configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository) + { + Q_ASSERT_X(pLoggerRepository, "PropertyConfigurator::configureRootLogger()", "pLoggerRepository must not be null."); + + const QLatin1String key_root_logger("log4j.rootLogger"); + const QLatin1String key_root_category("log4j.rootCategory"); + + // - Test for the logger/category prefix + // - Parse logger data for root logger + + QString key = key_root_logger; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + key = key_root_category; + value = OptionConverter::findAndSubst(rProperties, key); + if (!value.isNull()) + logger()->warn("[%1] is deprecated. Use [%2] instead.", key_root_category, key_root_logger); + } + + if (value.isNull()) + logger()->debug("Could not find root logger information. Is this correct?"); + else + parseLogger(rProperties, pLoggerRepository->rootLogger(), key, value); + } + + + void PropertyConfigurator::parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const + { + Q_ASSERT_X(pLogger, "parseAdditivityForLogger()", "pLogger must not be null."); + + const QLatin1String additivity_prefix("log4j.additivity."); + + // - Lookup additivity key for logger + // - Set additivity, if specified + + QString key = additivity_prefix + rLog4jName; + QString value = OptionConverter::findAndSubst(rProperties, key); + logger()->debug("Parsing additivity for logger: key '%1', value '%2'", key, value); + if (!value.isEmpty()) + { + bool additivity = OptionConverter::toBoolean(value, true); + logger()->debug("Setting additivity for logger '%1' to '%2'", pLogger->name(), QVariant(value).toString()); + pLogger->setAdditivity(additivity); + } + } + + + LogObjectPtr<Appender> PropertyConfigurator::parseAppender(const Properties &rProperties, + const QString &rName) + { + // - Test if appender has been parsed before + // - Find appender key + // - Create appender object + // - Set layout, if required by appender + // - Set properties + // - Activate options + // - Add appender to registry + + const QLatin1String appender_prefix("log4j.appender."); + + logger()->debug("Parsing appender named '%1'", rName); + + if (mAppenderRegistry.contains(rName)) + { + logger()->debug("Appender '%1' was already parsed.", rName); + return mAppenderRegistry.value(rName); + } + + QString key = appender_prefix + rName; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing appender definition for appender named '%1'"), + CONFIGURATOR_MISSING_APPENDER_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rName; + logger()->error(e); + return 0; + } + LogObjectPtr<Appender> p_appender = Factory::createAppender(value); + if (!p_appender) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create appender of class '%1' named '%2'"), + CONFIGURATOR_UNKNOWN_APPENDER_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rName; + logger()->error(e); + return 0; + } + p_appender->setName(rName); + + if (p_appender->requiresLayout()) + { + LogObjectPtr<Layout> p_layout = parseLayout(rProperties, key); + if (p_layout) + p_appender->setLayout(p_layout); + else + return 0; + } + + QStringList exclusions; + exclusions << QLatin1String("layout"); + setProperties(rProperties, key + QLatin1String("."), exclusions, p_appender); + AppenderSkeleton *p_appenderskeleton = qobject_cast<AppenderSkeleton *>(p_appender); + if (p_appenderskeleton) + p_appenderskeleton->activateOptions(); + + mAppenderRegistry.insert(rName, p_appender); + return p_appender; + } + + + LogObjectPtr<Layout> PropertyConfigurator::parseLayout(const Properties &rProperties, + const QString &rAppenderKey) + { + Q_ASSERT_X(!rAppenderKey.isEmpty(), "PropertyConfigurator::parseLayout()", "rAppenderKey must not be empty."); + + // - Find layout key + // - Create layput object + // - Set properties + // - Activate options + + const QLatin1String layout_suffix(".layout"); + + logger()->debug("Parsing layout for appender named '%1'", rAppenderKey); + + QString key = rAppenderKey + layout_suffix; + QString value = OptionConverter::findAndSubst(rProperties, key); + if (value.isNull()) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Missing layout definition for appender '%1'"), + CONFIGURATOR_MISSING_LAYOUT_ERROR, + "Log4Qt::PropertyConfigurator"); + e << rAppenderKey; + logger()->error(e); + return 0; + } + LogObjectPtr<Layout> p_layout = Factory::createLayout(value); + if (!p_layout) + { + LogError e = LOG4QT_ERROR(QT_TR_NOOP("Unable to create layoput of class '%1' requested by appender '%2'"), + CONFIGURATOR_UNKNOWN_LAYOUT_CLASS_ERROR, + "Log4Qt::PropertyConfigurator"); + e << value << rAppenderKey; + logger()->error(e); + return 0; + } + + QStringList exclusions; + setProperties(rProperties, key + QLatin1String("."), QStringList(), p_layout); + p_layout->activateOptions(); + + return p_layout; + } + + + void PropertyConfigurator::parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue) + { + Q_ASSERT_X(pLogger, "PropertyConfigurator::parseLogger()", "pLogger must not be null."); + Q_ASSERT_X(!rKey.isEmpty(), "PropertyConfigurator::parseLogger()", "rKey must not be empty."); + + const QLatin1String keyword_inherited("INHERITED"); + + // - Split value on comma + // - If level value, is specified + // - Test for NULL and INHERITED + // - Ensure root logger is not set to NULL + // - Set level + // - For each entry + // - Create Appender + + logger()->debug("Parsing logger: key '%1', value '%2'", rKey, rValue); + QStringList appenders = rValue.split(QLatin1Char(',')); + QStringListIterator i (appenders); + + // First entry is the level. There will be always one entry, even if the rValue is + // empty or does not contain a comma. + QString value = i.next().trimmed(); + if (!value.isEmpty()) + { + Level level; + if (value.compare(keyword_inherited,Qt::CaseInsensitive) == 0) + level = Level::NULL_INT; + else + level = OptionConverter::toLevel(value, Level::DEBUG_INT); + if (level == Level::NULL_INT && pLogger->name() == QString()) + logger()->warn("The root logger level cannot be set to NULL."); + else + { + pLogger->setLevel(level); + logger()->debug("Set level for logger '%1' to '%2'", + pLogger->name(), pLogger->level().toString()); + } + } + + pLogger->removeAllAppenders(); + while(i.hasNext()) + { + value = i.next().trimmed(); + if(value.isEmpty()) + continue; + LogObjectPtr<Appender> p_appender = parseAppender(rProperties, value); + if (p_appender) + pLogger->addAppender(p_appender); + } + } + + + void PropertyConfigurator::setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject) + { + Q_ASSERT_X(!rPrefix.isEmpty(), "PropertyConfigurator::setProperties()", "rPrefix must not be empty."); + Q_ASSERT_X(pObject, "PropertyConfigurator::setProperties()", "pObject must not be null."); + + // Iterate through all entries: + // - Test for prefix to determine, if setting is for object + // - Skip empty property name + // - Skip property names in exclusion list + // - Set property on object + + logger()->debug("Setting properties for object of class '%1' from keys starting with '%2'", + QLatin1String(pObject->metaObject()->className()), + rPrefix); + + QStringList keys = rProperties.propertyNames(); + QString key; + Q_FOREACH(key, keys) + { + if (!key.startsWith(rPrefix)) + continue; + QString property = key.mid(rPrefix.length()); + if (property.isEmpty()) + continue; + QStringList split_property = property.split(QLatin1Char('.')); + if (rExclusions.contains(split_property.at(0), Qt::CaseInsensitive)) + continue; + QString value = OptionConverter::findAndSubst(rProperties, key); + Factory::setObjectProperty(pObject, property, value); + } + } + + + void PropertyConfigurator::startCaptureErrors() + { + Q_ASSERT_X(!mpConfigureErrors, "PropertyConfigurator::startCaptureErrors()", "mpConfigureErrors must be empty."); + + mpConfigureErrors = new ListAppender; + mpConfigureErrors->setName(QLatin1String("PropertyConfigurator")); + mpConfigureErrors->setConfiguratorList(true); + mpConfigureErrors->setThreshold(Level::ERROR_INT); + LogManager::logLogger()->addAppender(mpConfigureErrors); + } + + + bool PropertyConfigurator::stopCaptureErrors() + { + Q_ASSERT_X(mpConfigureErrors, "PropertyConfigurator::stopCaptureErrors()", "mpConfigureErrors must not be empty."); + + LogManager::logLogger()->removeAppender(mpConfigureErrors); + ConfiguratorHelper::setConfigureError(mpConfigureErrors->list()); + bool result = (mpConfigureErrors->list().count() == 0); + mpConfigureErrors = 0; + return result; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator) + { + Q_UNUSED(rPropertyConfigurator); + debug.nospace() << "PropertyConfigurator(" + << ")"; + return debug.space(); + } +#endif + + + +} // namespace Log4Qt Logging diff --git a/ext/Log4Qt/src/propertyconfigurator.h b/ext/Log4Qt/src/propertyconfigurator.h new file mode 100755 index 0000000..23588a3 --- /dev/null +++ b/ext/Log4Qt/src/propertyconfigurator.h @@ -0,0 +1,194 @@ +/****************************************************************************** + * + * package: Logging + * file: propertyconfigurator.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_PROPERTYCONFIGURATOR_H +#define LOG4QT_PROPERTYCONFIGURATOR_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + + +#include <QtCore/QHash> +#include "helpers/logobjectptr.h" +#include "log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QSettings; + +namespace Log4Qt +{ + + class Appender; + class Layout; + class ListAppender; + class Logger; + class Properties; + class LoggerRepository; + + /*! + * \brief The class PropertyConfigurator allows the configuration of the + * package from a JAVA properties file. + * + * \note All the functions declared in this class are thread-safe. + */ + class LOG4QT_EXPORT PropertyConfigurator + { + public: + PropertyConfigurator(); + // virtual ~PropertyConfigurator(); // Use compiler default + private: + PropertyConfigurator(const PropertyConfigurator &rOther); // Not implemented + PropertyConfigurator &operator=(const PropertyConfigurator &rOther); // Not implemented + + public: + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const Properties &rProperties, + LoggerRepository *pLoggerRepository = 0); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + bool doConfigure(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository = 0); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + bool doConfigure(const QSettings &rSettings, + LoggerRepository *pLoggerRepository = 0); + + // JAVA: void doConfigure(const QUrl &rUrl, LoggerRepository *pLoggerRepository); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const Properties &rProperties); + + /*! + * \sa ConfiguratorHelper::configureError() + */ + static bool configure(const QString &rConfigFilename); + + /*! + * Reads the configuration data from the QSettings object + * \a rSettings. + * + * \sa \ref doConfigure(const QSettings &, LoggerRepository *) "doConfigure()", + * \ref Properties::load(const QSettings &) "Properties::load()", + * ConfiguratorHelper::configureError() + */ + static bool configure(const QSettings &rSettings); + + // JAVA: static void configure(const QUrl &rUrl); + + /*! + * \sa ConfiguratorHelper::configureError(), + * ConfiguratorHelper::configurationFile() + */ + static bool configureAndWatch(const QString &rConfigFilename); + + private: + void configureFromFile(const QString &rConfigFileName, + LoggerRepository *pLoggerRepository); + void configureFromProperties(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureFromSettings(const QSettings &rSettings, + LoggerRepository *pLoggerRepository); + void configureGlobalSettings(const Properties &rProperties, + LoggerRepository *pLoggerRepository) const; + void configureNonRootElements(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void configureRootLogger(const Properties &rProperties, + LoggerRepository *pLoggerRepository); + void parseAdditivityForLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rLog4jName) const; + LogObjectPtr<Appender> parseAppender(const Properties &rProperties, + const QString &rName); + LogObjectPtr<Layout> parseLayout(const Properties &rProperties, + const QString &rAppenderName); + void parseLogger(const Properties &rProperties, + Logger *pLogger, + const QString &rKey, + const QString &rValue); + void setProperties(const Properties &rProperties, + const QString &rPrefix, + const QStringList &rExclusions, + QObject *pObject); + void startCaptureErrors(); + bool stopCaptureErrors(); + + private: + LogObjectPtr<ListAppender> mpConfigureErrors; + QHash< QString, LogObjectPtr<Appender> > mAppenderRegistry; + }; + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + +#ifndef QT_NO_DEBUG_STREAM + /*! + * \relates PropertyConfigurator + * + * Writes all object member variables to the given debug stream \a debug + * and returns the stream. + * + * <tt> + * %PropertyConfigurator() + * </tt> + * \sa QDebug + */ + QDebug operator<<(QDebug debug, + const PropertyConfigurator &rPropertyConfigurator); +#endif + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline PropertyConfigurator::PropertyConfigurator() + {} + + +} // namspace Logging + + +// Q_DECLARE_TYPEINFO(Log4Qt::PropertyConfigurator, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_PROPERTYCONFIGURATOR_H diff --git a/ext/Log4Qt/src/rollingfileappender.cpp b/ext/Log4Qt/src/rollingfileappender.cpp new file mode 100755 index 0000000..9b13135 --- /dev/null +++ b/ext/Log4Qt/src/rollingfileappender.cpp @@ -0,0 +1,191 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.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 "rollingfileappender.h" + +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QTextCodec> +#include "helpers/optionconverter.h" +#include "layout.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************ + Declarations + *************************************************************************/ + + + + /************************************************************************ + C helper functions + *************************************************************************/ + + + + /************************************************************************ + Class implementation: RollingFileAppender + *************************************************************************/ + + + RollingFileAppender::RollingFileAppender(QObject *pParent) : + FileAppender(pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent) : + FileAppender(pLayout, rFileName, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent) : + FileAppender(pLayout, rFileName, append, pParent), + mMaxBackupIndex(1), + mMaximumFileSize(10*1024*1024) + { + } + + + RollingFileAppender::~RollingFileAppender() + { + close(); + } + + + void RollingFileAppender::setMaxFileSize(const QString &rMaxFileSize) + { + bool ok; + qint64 max_file_size = OptionConverter::toFileSize(rMaxFileSize, &ok); + if (ok) + setMaximumFileSize(max_file_size); + } + + + void RollingFileAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "RollingFileAppender::append()", "Lock must be held by caller") + + FileAppender::append(rEvent); + if (writer()->device()->size() > this->mMaximumFileSize) + rollOver(); + } + + + void RollingFileAppender::rollOver() + { + // Q_ASSERT_X(, "RollingFileAppender::rollOver()", "Lock must be held by caller") + + logger()->debug("Rolling over with maxBackupIndex = %1", mMaxBackupIndex); + + closeFile(); + + QFile f; + f.setFileName(file() + QLatin1Char('.') + QString::number(mMaxBackupIndex)); + if (f.exists() && !removeFile(f)) + return; + + QString target_file_name; + int i; + for (i = mMaxBackupIndex - 1; i >=1; i--) + { + f.setFileName(file() + QLatin1Char('.') + QString::number(i)); + if (f.exists()) + { + target_file_name = file() + QLatin1Char('.') + QString::number(i + 1); + if (!renameFile(f, target_file_name)) + return; + } + } + + f.setFileName(file()); + target_file_name = file() + QLatin1String(".1"); + if (!renameFile(f, target_file_name)) + return; + + openFile(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug RollingFileAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "RollingFileAppender(" + << "name:" << name() << " " + << "appendfile:" << appendFile() << " " + << "bufferedio:" << bufferedIo() << " " + << "encoding:" << codec_name << " " + << "file:" << file() << " " + << "filter:" << firstFilter() << " " + << "immediateflush:" << immediateFlush() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "maxbackupindex:" << maxBackupIndex() << " " + << "maximumfilesize:" << maximumFileSize() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() << " " + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/rollingfileappender.h b/ext/Log4Qt/src/rollingfileappender.h new file mode 100755 index 0000000..4b01af1 --- /dev/null +++ b/ext/Log4Qt/src/rollingfileappender.h @@ -0,0 +1,169 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: rollingfileappender.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_ROLINGFILEAPPENDER_H +#define LOG4QT_ROLINGFILEAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "fileappender.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class RollingFileAppender extends FileAppender to backup + * the log files when they reach a certain size. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT RollingFileAppender : public FileAppender + { + Q_OBJECT + + /*! + * The property holds the maximum backup count used by the appender. + * + * The default is 1. + * + * \sa maxBackupIndex(), setMaxBackupIndex() + */ + Q_PROPERTY(int maxBackupIndex READ maxBackupIndex WRITE setMaxBackupIndex) + + /*! + * The property holds the maximum file size used by the appender. + * + * The default is 10 MB (10 * 1024 * 1024). + * + * \sa maximumFileSize(), setMaximumFileSize() + */ + Q_PROPERTY(qint64 maximumFileSize READ maximumFileSize WRITE setMaximumFileSize) + + /*! + * The property sets the maximum file size from a string value. + * + * \sa setMaxFileSize(), maximumFileSize() + */ + Q_PROPERTY(QString maxFileSize READ maxFileSize WRITE setMaxFileSize) + + public: + RollingFileAppender(QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + QObject *pParent = 0); + RollingFileAppender(Layout *pLayout, + const QString &rFileName, + bool append, + QObject *pParent = 0); + virtual ~RollingFileAppender(); + private: + RollingFileAppender(const RollingFileAppender &rOther); // Not implemented + RollingFileAppender &operator=(const RollingFileAppender &rOther); // Not implemented + + public: + int maxBackupIndex() const; + qint64 maximumFileSize() const; + QString maxFileSize() const; + void setMaxBackupIndex(int maxBackupIndex); + void setMaximumFileSize(qint64 maximumFileSize); + void setMaxFileSize(const QString &rMaxFileSize); + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %RollingFileAppender(name:"RFA" appendfile:false bufferedio:true + * encoding:"" file:"log.txt" filter: 0x0 + * immediateflush:true isactive:true + * isclosed:false layout:"TTCC" maxbackupindex:2 + * maximumfilesize:40 referencecount:1 + * threshold:"NULL" writer:0x4175af8) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void rollOver(); + + private: + int mMaxBackupIndex; + qint64 mMaximumFileSize; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline int RollingFileAppender::maxBackupIndex() const + { QMutexLocker locker(&mObjectGuard); + return mMaxBackupIndex; } + + inline qint64 RollingFileAppender::maximumFileSize() const + { QMutexLocker locker(&mObjectGuard); + return mMaximumFileSize; } + + inline QString RollingFileAppender::maxFileSize() const + { QMutexLocker locker(&mObjectGuard); + return QString::number(mMaximumFileSize); } + + inline void RollingFileAppender::setMaxBackupIndex(int maxBackupIndex) + { QMutexLocker locker(&mObjectGuard); + mMaxBackupIndex = maxBackupIndex; } + + inline void RollingFileAppender::setMaximumFileSize(qint64 maximumFileSize) + { QMutexLocker locker(&mObjectGuard); + mMaximumFileSize = maximumFileSize; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::RollingFileAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_ROLINGFILEAPPENDER_H diff --git a/ext/Log4Qt/src/signalappender.cpp b/ext/Log4Qt/src/signalappender.cpp new file mode 100755 index 0000000..f180d18 --- /dev/null +++ b/ext/Log4Qt/src/signalappender.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: signalappender.cpp + * created: March 2010 + * author: Filonenko Michael + * + * + * Copyright 2010 Filonenko Michael + * + * 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 "signalappender.h" + +#include "layout.h" + +#include <QtCore/QDebug> + +namespace Log4Qt { + SignalAppender::SignalAppender(QObject *parent) : + AppenderSkeleton(parent) + { + } + + void SignalAppender::append(const LoggingEvent &rEvent) + { + QString message(layout()->format(rEvent)); + emit appended(message); + } + +#ifndef QT_NO_DEBUG_STREAM + QDebug SignalAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "WriterAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() + << "isactive:" << isActive() + << "isclosed:" << isClosed() + << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + +} diff --git a/ext/Log4Qt/src/signalappender.h b/ext/Log4Qt/src/signalappender.h new file mode 100755 index 0000000..4fca738 --- /dev/null +++ b/ext/Log4Qt/src/signalappender.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: signalappender.h + * created: March 2010 + * author: Filonenko Michael + * + * + * Copyright 2010 Filonenko Michael + * + * 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 SIGNALAPPENDER_H +#define SIGNALAPPENDER_H + +#include "appenderskeleton.h" + +#include "loggingevent.h" + +namespace Log4Qt { + + /*! + \ingroup log4qt + Класс генерирующий сигнал при полчении какого-либо лог-сообщения. Удобно использовать для GUI интерфейса. + \note не объявлен в простанстве имен log4qt вроде из-за отстуствия у moc (Qt metaobject compiler) средств для обработки пространств имен. +* @class SignalAppender signalappender.h "src/kernel/components/signalappender.h" +*/ + class LOG4QT_EXPORT SignalAppender : public AppenderSkeleton + { + Q_OBJECT + public: + explicit SignalAppender(QObject *parent = 0); + + bool requiresLayout() const; + + protected: + virtual void append(const Log4Qt::LoggingEvent &rEvent); + +#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; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug debug, + const LogObject &rLogObject); +#endif // QT_NO_DEBUG_STREAM + + signals: + /*! + Генерируется во время получения лог-сообщения. + * @param message + */ + void appended(const QString& message); + public slots: + + }; + + inline bool SignalAppender::requiresLayout() const + { return true; } + +} // namespace Log4Qt + +#endif // SIGNALAPPENDER_H diff --git a/ext/Log4Qt/src/simplelayout.cpp b/ext/Log4Qt/src/simplelayout.cpp new file mode 100755 index 0000000..36ce26f --- /dev/null +++ b/ext/Log4Qt/src/simplelayout.cpp @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.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 "simplelayout.h" + +#include <QtCore/QDebug> +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: SimpleLayout + **************************************************************************/ + + + QString SimpleLayout::format(const LoggingEvent &rEvent) + { + return rEvent.level().toString() + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug SimpleLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "SimpleLayout(" + << "name:" << name() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/simplelayout.h b/ext/Log4Qt/src/simplelayout.h new file mode 100755 index 0000000..fbf6545 --- /dev/null +++ b/ext/Log4Qt/src/simplelayout.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simplelayout.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_SIMPLELAYOUT_H +#define LOG4QT_SIMPLELAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class SimpleLayout outputs the level and message of a logging + * event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT SimpleLayout : public Layout + { + Q_OBJECT + + public: + SimpleLayout(QObject *pParent = 0); + // virtual ~SimpleLayout(); // Use compiler default + private: + SimpleLayout(const SimpleLayout &rOther); // Not implemented + SimpleLayout &operator=(const SimpleLayout &rOther); // Not implemented + + public: + virtual QString format(const LoggingEvent &rEvent); + + protected: + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %SimpleLayout(name:"SL" referencecount:1) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline SimpleLayout::SimpleLayout(QObject *pParent) : + Layout(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::SimpleLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_SIMPLELAYOUT_H diff --git a/ext/Log4Qt/src/simpletimelayout.cpp b/ext/Log4Qt/src/simpletimelayout.cpp new file mode 100755 index 0000000..7e73295 --- /dev/null +++ b/ext/Log4Qt/src/simpletimelayout.cpp @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simpletimelayout.cpp + * created: March 2010 + * author: Filonenko Michael + * + * + * Copyright 2010 Filonenko Michael + * + * + * 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 "simpletimelayout.h" + +#include <QtCore/QDebug> +#include "loggingevent.h" +#include "helpers/datetime.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: SimpleTimeLayout + **************************************************************************/ + + + QString SimpleTimeLayout::format(const LoggingEvent &rEvent) + { + return DateTime::fromMilliSeconds(rEvent.timeStamp()).toString("dd.MM.yyyy hh:mm") + + QLatin1String("[") + rEvent.threadName() + QLatin1String("]") + + QLatin1String(" ") + rEvent.level().toString() + + QLatin1String(" ") + rEvent.loggerName() + + QLatin1String(" - ") + rEvent.message() + Layout::endOfLine(); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug SimpleTimeLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "SimpleTimeLayout(" + << "name:" << name() << " " + << "referencecount:" << referenceCount() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/simpletimelayout.h b/ext/Log4Qt/src/simpletimelayout.h new file mode 100755 index 0000000..297f495 --- /dev/null +++ b/ext/Log4Qt/src/simpletimelayout.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: simpletimelayout.h + * created: March 2010 + * author: Filonenko Michael + * + * + * Copyright 2010 Filonenko Michael + * + * 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_SIMPLETIMELAYOUT_H +#define LOG4QT_SIMPLETIMELAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + +namespace Log4Qt +{ + + /*! + * \brief The class SimpleTimeLayout outputs the time, logger name, thread, level and message of a logging + * event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT SimpleTimeLayout : public Layout + { + Q_OBJECT + + public: + SimpleTimeLayout(QObject *pParent = 0); + // virtual ~SimpleTimeLayout(); // Use compiler default + private: + SimpleTimeLayout(const SimpleTimeLayout &rOther); // Not implemented + SimpleTimeLayout &operator=(const SimpleTimeLayout &rOther); // Not implemented + + public: + virtual QString format(const LoggingEvent &rEvent); + + protected: + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %SimpleTimeLayout(name:"SL" referencecount:1) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline SimpleTimeLayout::SimpleTimeLayout(QObject *pParent) : + Layout(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::SimpleTimeLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_SIMPLETIMELAYOUT_H diff --git a/ext/Log4Qt/src/spi/filter.cpp b/ext/Log4Qt/src/spi/filter.cpp new file mode 100755 index 0000000..31c1c9a --- /dev/null +++ b/ext/Log4Qt/src/spi/filter.cpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.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 "spi/filter.h" + +#include <QtCore/QDebug> + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + void Filter::setNext(Filter *pFilter) + { + mpNext = pFilter; + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/spi/filter.h b/ext/Log4Qt/src/spi/filter.h new file mode 100755 index 0000000..99861d8 --- /dev/null +++ b/ext/Log4Qt/src/spi/filter.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: filter.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_FILTER_H +#define LOG4QT_FILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "helpers/logobject.h" + +#include "helpers/logobjectptr.h" +#include "../log4qt.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + + /*! + * \brief The class Filter is the base class for all filters. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT Filter : public LogObject + { + Q_OBJECT + + /*! + * The property holds the next filter of this filter. + * + * The default is 0 for no next filter. + * + * \sa next(), setNext() + */ + Q_PROPERTY(Filter* next READ next WRITE setNext) + + public: + enum Decision + { + ACCEPT, + DENY, + NEUTRAL + }; + Q_ENUMS(Decision) + + public: + Filter(QObject *pObject = 0); + // Filter(const Filter &rOther); // Use compiler default + virtual ~Filter(); + // Filter &operator=(const Filter &rOther); // Use compiler default + + Filter* next() const; + void setNext(Filter *pFilter); + + virtual void activateOptions(); + virtual Decision decide(const LoggingEvent &rEvent) const = 0; + + private: + LogObjectPtr<Filter> mpNext; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline Filter::Filter(QObject *pObject) : + LogObject(pObject), + mpNext(0) + {} + + inline Filter::~Filter() + {} + + inline Filter* Filter::next() const + { return mpNext; } + + inline void Filter::activateOptions() + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::Filter, Q_COMPLEX_TYPE); // Use default +Q_DECLARE_TYPEINFO(Log4Qt::LogObjectPtr<Log4Qt::Filter>, Q_MOVABLE_TYPE); + + +#endif // LOG4QT_FILTER_H diff --git a/ext/Log4Qt/src/systemlogappender.cpp b/ext/Log4Qt/src/systemlogappender.cpp new file mode 100644 index 0000000..806a50a --- /dev/null +++ b/ext/Log4Qt/src/systemlogappender.cpp @@ -0,0 +1,181 @@ +#include "systemlogappender.h" + +#include "layout.h" +#include "level.h" +#include "loggingevent.h" + +#include <QtCore/QDebug> +#include <QtCore/QCoreApplication> + +#if defined(Q_OS_WIN32) +#ifndef UNICODE +#define UNICODE +#endif +#include <qt_windows.h> +#include <QtCore/QLibrary> + + + +typedef HANDLE(WINAPI*PDeregisterEventSource)(HANDLE); +static PDeregisterEventSource pDeregisterEventSource = 0; +typedef BOOL(WINAPI*PReportEvent)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCTSTR*,LPVOID); +static PReportEvent pReportEvent = 0; +typedef HANDLE(WINAPI*PRegisterEventSource)(LPCTSTR,LPCTSTR); +static PRegisterEventSource pRegisterEventSource = 0; + +#define RESOLVE(name) p##name = (P##name)lib.resolve(#name); +#define RESOLVEA(name) p##name = (P##name)lib.resolve(#name"A"); +#define RESOLVEW(name) p##name = (P##name)lib.resolve(#name"W"); + +static bool winServiceInit() +{ + if (!pDeregisterEventSource) { + QLibrary lib("advapi32"); + + // only resolve unicode versions + RESOLVE(DeregisterEventSource); + RESOLVEW(ReportEvent); + RESOLVEW(RegisterEventSource); + } + return pDeregisterEventSource != 0; +} +#else + +#include <pwd.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <signal.h> +#include <sys/stat.h> + +static QString encodeName(const QString &name, bool allowUpper = false) +{ + QString n = name.toLower(); + QString legal = QLatin1String("abcdefghijklmnopqrstuvwxyz1234567890"); + if (allowUpper) + legal += QLatin1String("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + int pos = 0; + while (pos < n.size()) { + if (legal.indexOf(n[pos]) == -1) + n.remove(pos, 1); + else + ++pos; + } + return n; +} +#endif //#if defined(Q_OS_WIN32) +namespace Log4Qt { + SystemLogAppender::SystemLogAppender(QObject *parent) : + AppenderSkeleton(parent), ident(0) + { + setServiceName(QCoreApplication::applicationName()); + } + + SystemLogAppender::~SystemLogAppender() + { + if (ident) + delete[] ident; + } + + void SystemLogAppender::append(const LoggingEvent &rEvent) + { + QString message(layout()->format(rEvent)); + +#if defined(Q_OS_WIN32) + // Q_D(QtServiceBase); + if (!winServiceInit()) + return; + WORD wType; + switch (rEvent.level().toInt()) { + case Level::WARN_INT: + wType = EVENTLOG_WARNING_TYPE; + break; + case Level::ERROR_INT: + wType = EVENTLOG_ERROR_TYPE; + break; + case Level::FATAL_INT: + wType = EVENTLOG_ERROR_TYPE; + break; + case Level::OFF_INT: + wType = EVENTLOG_SUCCESS; + break; + default: + wType = EVENTLOG_INFORMATION_TYPE; + break; + } + + HANDLE h = pRegisterEventSource(0, (wchar_t *) serviceName().utf16()); + if (h) { + int id = 0; + uint category = 0; + const wchar_t *msg = (wchar_t*) message.utf16(); + const char *bindata = 0;//data.size() ? data.constData() : 0; + const int datasize = 0; + pReportEvent(h, wType, category, id, 0, 1, datasize, + (const wchar_t **) &msg, const_cast<char *> (bindata)); + pDeregisterEventSource(h); + } +#else + + int st; + switch (rEvent.level().toInt()) { + case Level::WARN_INT: + st = LOG_WARNING; + break; + case Level::ERROR_INT: + st = LOG_ERR; + break; + case Level::FATAL_INT: + st = LOG_ERR; + break; + default: + st = LOG_INFO; + } + + openlog(ident, LOG_PID, LOG_DAEMON); + foreach(const QString& line, message.split('\n', QString::SkipEmptyParts)) + syslog(st, "%s", line.toLocal8Bit().constData()); + closelog(); + +#endif //#if defined(Q_OS_WIN32) + } + + QString SystemLogAppender::serviceName() const + { + return mServiceName; + } + + void SystemLogAppender::setServiceName(const QString& serviceName) + { + mServiceName = serviceName; + +#if !defined(Q_OS_WIN32) + if (ident) + delete[] ident; + QString tmp = encodeName(mServiceName, true); + int len = tmp.toLocal8Bit().size(); + ident = new char[len + 1]; + ident[len] = '\0'; + ::memcpy(ident, tmp.toLocal8Bit().constData(), len); +#endif + } + +#ifndef QT_NO_DEBUG_STREAM + QDebug SystemLogAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "WriterAppender(" << "name:" << name() << " " + << "filter:" << firstFilter() << "isactive:" << isActive() << "isclosed:" + << isClosed() << "layout:" << layout_name << "referencecount:" + << referenceCount() << " " << "threshold:" << threshold().toString() + << "serviceName:" << serviceName() << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM +} + diff --git a/ext/Log4Qt/src/systemlogappender.h b/ext/Log4Qt/src/systemlogappender.h new file mode 100644 index 0000000..ad8325d --- /dev/null +++ b/ext/Log4Qt/src/systemlogappender.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: databaseappender.h + * created: December 2010 + * author: Michael Filonenko + * + * + * Copyright 2010 Michael Filonenko + * + * 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 SYSTEMLOGAPPENDER_H +#define SYSTEMLOGAPPENDER_H + +#include "appenderskeleton.h" + +namespace Log4Qt { + + /*! + * \brief The class SystemLogAppender appends log events to a Event Log under win* + * and to syslog under *nix. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT SystemLogAppender: public AppenderSkeleton + { + Q_OBJECT + + /** + * The property holds the port used by the telenet appender. + * + * The default is QCoreApplication::applicationName() + * + * \sa serviceName(), setServiceName() + */ + Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName) + public: + explicit SystemLogAppender(QObject *parent = 0); + ~SystemLogAppender(); + + bool requiresLayout() const; + + /** + * + * + */ + QString serviceName() const; + /** + * + */ + void setServiceName(const QString& serviceName); + + protected: + virtual void append(const Log4Qt::LoggingEvent &rEvent); + +#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; + + // Needs to be friend to access internal data + friend QDebug operator<<(QDebug debug, const LogObject &rLogObject); +#endif // QT_NO_DEBUG_STREAM + QString mServiceName; + char *ident; + }; + + inline bool SystemLogAppender::requiresLayout() const + { + return true; + } + +} + +#endif //#ifndef SYSTEMLOGAPPENDER_H diff --git a/ext/Log4Qt/src/telnetappender.cpp b/ext/Log4Qt/src/telnetappender.cpp new file mode 100644 index 0000000..4c96e9f --- /dev/null +++ b/ext/Log4Qt/src/telnetappender.cpp @@ -0,0 +1,255 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: telnetappender.cpp + * created: July 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. + * + ******************************************************************************/ + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "telnetappender.h" + +#include <QtCore/QDebug> + +#include <QtNetwork/QTcpServer> +#include <QtNetwork/QTcpSocket> +#include <QtNetwork/QHostAddress> + +#include "layout.h" +#include "loggingevent.h" + +namespace Log4Qt { + /************************************************************************** + * Declarations + **************************************************************************/ + + /************************************************************************** + * C helper functions + **************************************************************************/ + + /************************************************************************** + * Class implementation: TelnetAppender + **************************************************************************/ + + TelnetAppender::TelnetAppender(QObject *pParent) : + AppenderSkeleton(false, pParent), mAddress(QHostAddress::Any), mPort(23), + mpTcpServer(0), mImmediateFlush(false) + { + } + + TelnetAppender::TelnetAppender(Layout *pLayout, QObject *pParent) : + AppenderSkeleton(false, pParent), mAddress(QHostAddress::Any), mPort(23), + mpTcpServer(0), mImmediateFlush(false) + { + setLayout(pLayout); + } + + TelnetAppender::TelnetAppender(Layout *pLayout, int port, QObject *pParent) : + AppenderSkeleton(false, pParent), mAddress(QHostAddress::Any), mPort(port), + mpTcpServer(0), mImmediateFlush(false) + { + setLayout(pLayout); + } + + TelnetAppender::TelnetAppender(Layout *pLayout, const QHostAddress& address, + int port, QObject *pParent) : + AppenderSkeleton(false, pParent), mAddress(address), mPort(port), + mpTcpServer(0), mImmediateFlush(false) + { + setLayout(pLayout); + } + + TelnetAppender::~TelnetAppender() + { + close(); + } + + void TelnetAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + closeServer(); + openServer(); + + AppenderSkeleton::activateOptions(); + } + + void TelnetAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + AppenderSkeleton::close(); + closeServer(); + } + + void TelnetAppender::setAddress(const QHostAddress& address) + { + mAddress = address; + } + + QHostAddress TelnetAppender::address() const + { + return mAddress; + } + + void TelnetAppender::setPort(int port) + { + mPort = port; + } + + int TelnetAppender::port() const + { + return mPort; + } + + void TelnetAppender::setWelcomeMessage(const QString & welcomeMessage) + { + mWelcomeMessage = welcomeMessage; + } + + bool TelnetAppender::requiresLayout() const + { + return true; + } + + void TelnetAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "TelnetAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "TelnetAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); + + Q_FOREACH (QTcpSocket * pClientConnection, mTcpSockets) + { + pClientConnection->write(message.toLocal8Bit().constData()); + if (immediateFlush()) + pClientConnection->flush(); + } + } + + bool TelnetAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "TelnetAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!mpTcpServer && !mpTcpServer->isListening()) { + LogError + e = + LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a listing telnet server"), + APPENDER_TELNET_SERVER_NOT_RUNNING); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); + } + + void TelnetAppender::openServer() + { + mpTcpServer = new QTcpServer(this); + connect(mpTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection())); + mpTcpServer->listen(mAddress, mPort); + } + + void TelnetAppender::closeServer() + { + if (mpTcpServer) + mpTcpServer->close(); + + Q_FOREACH(QTcpSocket * pClientConnection, mTcpSockets) + delete pClientConnection; + + mTcpSockets.clear(); + + delete mpTcpServer; + mpTcpServer = 0; + } + + QList<QTcpSocket*> TelnetAppender::clients() const + { + return mTcpSockets; + } + +#ifndef QT_NO_DEBUG_STREAM + QDebug TelnetAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "TelnetAppender(" << "name:" << name() << " " + << "filter:" << firstFilter() << "isactive:" << isActive() + << "isclosed:" << isClosed() << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " << "threshold:" + << threshold().toString() << "address:" << address() << "port:" + << port() << " " << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + bool TelnetAppender::handleIoErrors() const + { + // Q_ASSERT_X(, "FileAppender::handleIoErrors()", "Lock must be held by caller") + return false; + } + + void TelnetAppender::onNewConnection() + { + QMutexLocker locker(&mObjectGuard); + + if (mpTcpServer && mpTcpServer->hasPendingConnections()) { + QTcpSocket * pClientConnection = mpTcpServer->nextPendingConnection(); + if (pClientConnection) { + mTcpSockets.append(pClientConnection); + connect(pClientConnection, SIGNAL(disconnected()), this, + SLOT(onClientDisconnected())); + sendWelcomeMessage(pClientConnection); + } + } + } + + void TelnetAppender::sendWelcomeMessage(QTcpSocket * pClientConnection) + { + if (mWelcomeMessage.isEmpty()) + return; + + pClientConnection->write(mWelcomeMessage.toLocal8Bit().constData()); + } + + void TelnetAppender::onClientDisconnected() + { + QMutexLocker locker(&mObjectGuard); + + QTcpSocket* pClientConnection = qobject_cast<QTcpSocket*> (sender()); + if (pClientConnection) { + mTcpSockets.removeOne(pClientConnection); + pClientConnection->deleteLater(); + } + } + +/****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/telnetappender.h b/ext/Log4Qt/src/telnetappender.h new file mode 100644 index 0000000..b1c2021 --- /dev/null +++ b/ext/Log4Qt/src/telnetappender.h @@ -0,0 +1,228 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: telnetappender.h + * created: July 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_TELNETAPPENDER_H +#define LOG4QT_TELNETAPPENDER_H + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" + +#include <QtCore/QString> + +#include <QtNetwork/QHostAddress> + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QTcpServer; +class QTcpSocket; + +namespace Log4Qt +{ + + /*! + * \brief The class TelnetAppender appends log events to a read-only socket (telnet) + *T + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT TelnetAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds the port used by the telenet appender. + * + * The default is 23 for the port. + * + * \sa port, port(), setPort() + */ + Q_PROPERTY(int port READ port WRITE setPort) + + /*! + * The property holds, if the writer flushes after all write operations. + * + * The default is false for flushing. + * + * \sa immediateFlush(), setImmediateFlush() + */ + Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush) + + Q_PROPERTY(QHostAddress address READ address WRITE setAddress) + + public: + TelnetAppender(QObject *pParent = 0); + TelnetAppender(Layout *pLayout, + QObject *pParent = 0); + TelnetAppender(Layout *pLayout, + const QHostAddress& address, + int port, + QObject *pParent = 0); + TelnetAppender(Layout *pLayout, + int port, + QObject *pParent = 0); + virtual ~TelnetAppender(); + + private: + TelnetAppender(const TelnetAppender &rOther); // Not implemented + TelnetAppender &operator=(const TelnetAppender &rOther); // Not implemented + + public: + virtual bool requiresLayout() const; + virtual void activateOptions(); + virtual void close(); + + /*! + * Sets the listening port of the telnet server (default = 23) + */ + void setPort(int port); + /*! + * Returns the listening port of the telnet server + */ + int port() const; + /*! + * Set the property immediate flush (default: false) + */ + void setImmediateFlush(bool immediateFlush); + /*! + * Returns <true> immediate flush is enabled + */ + bool immediateFlush() const; + + /*! + * Sets the listenning address of the telnet server (default QHostAddress::Any) + */ + void setAddress(const QHostAddress& address); + /*! + * Returns the listenning address of the telnet server + */ + QHostAddress address() const; + /*! + * Set the welcome message which is send on + */ + void setWelcomeMessage(const QString & welcomeMessage); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + /*! + * Creates and starts (listening) the TCP server + */ + void openServer(); + /*! + * Stops and destroys the TCP server + */ + void closeServer(); + + QList<QTcpSocket*> clients() const; + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %TelnetAppender(name:"WA" filter:"0x0" + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL port:"23") + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + virtual bool handleIoErrors() const; + + private slots: + /*! + * Handles a new incomming connection + */ + void onNewConnection(); + /*! + * Handles a client disconnect + */ + void onClientDisconnected(); + + private: + QHostAddress mAddress; + int mPort; + QTcpServer * mpTcpServer; + QList<QTcpSocket*> mTcpSockets; + QString mWelcomeMessage; + volatile bool mImmediateFlush; + + void sendWelcomeMessage(QTcpSocket * pClientConnection); + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool TelnetAppender::immediateFlush() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mImmediateFlush; } + + inline void TelnetAppender::setImmediateFlush(bool immediateFlush) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mImmediateFlush = immediateFlush; } + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::TelnetAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_TELNETAPPENDER_H diff --git a/ext/Log4Qt/src/ttcclayout.cpp b/ext/Log4Qt/src/ttcclayout.cpp new file mode 100755 index 0000000..cb1d36f --- /dev/null +++ b/ext/Log4Qt/src/ttcclayout.cpp @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.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 "ttcclayout.h" + +#include <QtCore/QDebug> +#include <QtCore/QDateTime> +#include "helpers/datetime.h" +#include "helpers/patternformatter.h" +#include "logger.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: TTCCLayout + **************************************************************************/ + + + TTCCLayout::TTCCLayout(QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(RELATIVE); + } + + + TTCCLayout::TTCCLayout(const QString &rDateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(rDateFormat), + mThreadPrinting(true), + mpPatternFormatter(0) + { + } + + + TTCCLayout::TTCCLayout(DateFormat dateFormat, + QObject *pParent) : + Layout(pParent), + mCategoryPrefixing(true), + mContextPrinting(true), + mDateFormat(), + mThreadPrinting(true), + mpPatternFormatter(0) + { + setDateFormat(dateFormat); + } + + + TTCCLayout::~TTCCLayout() + { + delete mpPatternFormatter; + } + + + void TTCCLayout::setDateFormat(DateFormat dateFormat) + { + switch (dateFormat) + { + case NONE: + setDateFormat(QLatin1String("NONE")); + break; + case ISO8601: + setDateFormat(QLatin1String("ISO8601")); + break; + case ABSOLUTE: + setDateFormat(QLatin1String("ABSOLUTE")); + break; + case DATE: + setDateFormat(QLatin1String("DATE")); + break; + case RELATIVE: + setDateFormat(QLatin1String("RELATIVE")); + break; + default: + Q_ASSERT_X(false, "TTCCLayout::setDateFormat", "Unkown DateFormat"); + setDateFormat(QString()); + } + } + + + QString TTCCLayout::format(const LoggingEvent &rEvent) + { + Q_ASSERT_X(mpPatternFormatter, "TTCCLayout::format()", "mpPatternConverter must not be null"); + + return mpPatternFormatter->format(rEvent); + } + + + void TTCCLayout::updatePatternFormatter() + { + QString pattern; + + pattern += QLatin1String("%d{") + mDateFormat + QLatin1String("}"); + if (mThreadPrinting) + pattern += QLatin1String(" [%t]"); + pattern += QLatin1String(" %-5p"); + if (mCategoryPrefixing) + pattern += QLatin1String(" %c"); + if (mContextPrinting) + pattern += QLatin1String(" %x"); + pattern += QLatin1String(" - %m%n"); + + delete mpPatternFormatter; + mpPatternFormatter = new PatternFormatter(pattern); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug TTCCLayout::debug(QDebug &rDebug) const + { + rDebug.nospace() << "TTCCLayout(" + << "name:" << name() << " " + << "categoryprefixing:" << categoryPrefixing() << " " + << "contextprinting:" << contextPrinting() << " " + << "dateformat:" << dateFormat() << " " + << "referencecount:" << referenceCount() << " " + << "threadprinting:" << threadPrinting() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/ttcclayout.h b/ext/Log4Qt/src/ttcclayout.h new file mode 100755 index 0000000..3375a67 --- /dev/null +++ b/ext/Log4Qt/src/ttcclayout.h @@ -0,0 +1,235 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: ttcclayout.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_TTCCLAYOUT_H +#define LOG4QT_TTCCLAYOUT_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "layout.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + class LoggingEvent; + class PatternFormatter; + + /*! + * \brief The class TTCCLayout outputs the time, thread, logger and nested + * diagnostic context information of a logging event. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT TTCCLayout : public Layout + { + Q_OBJECT + + /*! + * The property holds if the logger name is part of the formatted output. + * + * The default value is true for including the logger name. + * + * \sa categoryPrefixing(), setCategoryPrefixing() + */ + Q_PROPERTY(bool categoryPrefixing READ categoryPrefixing WRITE setCategoryPrefixing) + + /*! + * The property holds if the nested context information is part of the + * formatted output. + * + * The default value it true for including the nested context information. + * + * \sa contextPrinting(), setContextPrinting() + */ + Q_PROPERTY(bool contextPrinting READ contextPrinting WRITE setContextPrinting) + + /*! + * The property holds the date format used by the layout. + * + * The default date format is "RELATIVE". + * + * \sa dateFormat(), setDateFormat() + */ + Q_PROPERTY(QString dateFormat READ dateFormat WRITE setDateFormat) + + /*! + * The property holds if the thread name is part of the formatted output. + * + * The default value it true for including the thread name. + * + * \sa threadPrinting(), setThreadPrinting() + */ + Q_PROPERTY(bool threadPrinting READ threadPrinting WRITE setThreadPrinting) + + public: + /*! + * The enum DateFormat defines constants for date formats. + * + * \sa setDateFormat(DateFormat), DateTime::toString() + */ + enum DateFormat + { + /*! The none date format string is "NONE". */ + NONE, + /*! + * The iso8601 date format string is "ISO8601". The date will be + * formatted as yyyy-MM-dd hh:mm:ss.zzz. + */ + ISO8601, + /*! + * The absolute date format string is "ABSOLUTE". The date will be + * formatted as HH:mm:ss.zzz. + */ + ABSOLUTE, + /*! + * The date date format string is "DATE". The date will be formatted + * as MMM YYYY HH:mm:ss.zzzz. + */ + DATE, + /*! + * The relative date format string is "RELATIVE". The date will be + * formatted as milliseconds since start of the program. + */ + RELATIVE + }; + Q_ENUMS(DateFormat) + + TTCCLayout(QObject *pParent = 0); + TTCCLayout(const QString &rDateFormat, + QObject *pParent = 0); + + /*! + * Creates a TTCCLayout with the date formar value specified by + * the \a dateFormat constant and the parent \a pParent. + */ + TTCCLayout(DateFormat dateFormat, + QObject *pParent = 0); + + virtual ~TTCCLayout(); + private: + TTCCLayout(const TTCCLayout &rOther); // Not implemented + TTCCLayout &operator=(const TTCCLayout &rOther); // Not implemented + + public: + bool categoryPrefixing() const; + bool contextPrinting() const; + QString dateFormat() const; + // JAVA: bool ignoresThrowable() const; + bool threadPrinting() const; + void setCategoryPrefixing(bool categoryPrefixing); + void setContextPrinting(bool contextPrinting); + void setDateFormat(const QString &rDateFormat); + + /*! + * Sets the date format to the value specified by the \a dateFormat + * constant. + */ + void setDateFormat(DateFormat dateFormat); + + // JAVA: setIgnoresThrowable(bool ignoresThrowable); + void setThreadPrinting(bool threadPrinting); + virtual QString format(const LoggingEvent &rEvent); + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %TTCCLayout(name:"TTCC" categoryprefixing:true + * contextprinting:true dateformat:"ISO8601" + * referencecount:1 threadprinting:true) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + void updatePatternFormatter(); + + private: + bool mCategoryPrefixing; + bool mContextPrinting; + QString mDateFormat; + bool mThreadPrinting; + PatternFormatter *mpPatternFormatter; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool TTCCLayout::categoryPrefixing() const + { return mCategoryPrefixing; } + + inline bool TTCCLayout::contextPrinting() const + { return mContextPrinting; } + + inline QString TTCCLayout::dateFormat() const + { return mDateFormat; } + + inline bool TTCCLayout::threadPrinting() const + { return mThreadPrinting; } + + inline void TTCCLayout::setCategoryPrefixing(bool categoryPrefixing) + { mCategoryPrefixing = categoryPrefixing; + updatePatternFormatter(); } + + inline void TTCCLayout::setContextPrinting(bool contextPrinting) + { mContextPrinting = contextPrinting; + updatePatternFormatter(); } + + inline void TTCCLayout::setDateFormat(const QString &rDateFormat) + { mDateFormat = rDateFormat; + updatePatternFormatter(); } + + inline void TTCCLayout::setThreadPrinting(bool threadPrinting) + { mThreadPrinting = threadPrinting; + updatePatternFormatter(); } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::TTCCLayout, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_TTCCLAYOUT_H diff --git a/ext/Log4Qt/src/varia/debugappender.cpp b/ext/Log4Qt/src/varia/debugappender.cpp new file mode 100755 index 0000000..c77ee33 --- /dev/null +++ b/ext/Log4Qt/src/varia/debugappender.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.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 "varia/debugappender.h" + +#include <QtCore/QDebug> +#include <iostream> + +#include "layout.h" +#include "loggingevent.h" + +#if defined(Q_OS_WIN32) +#include <windows.h> +#endif + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: DebugAppender + **************************************************************************/ + + + DebugAppender::DebugAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(pParent) + { + setLayout(pLayout); + } + + + bool DebugAppender::requiresLayout() const + { + return true; + } + + + void DebugAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "DebugAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "DebugAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); +#if defined(Q_OS_WIN32) +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + QT_WA({ + OutputDebugStringW(reinterpret_cast<const WCHAR*>(message.utf16())); + }, { + OutputDebugStringA(message.toLocal8Bit().data()); + }); +#else + OutputDebugStringW(reinterpret_cast<const WCHAR*>(message.utf16())); +#endif +#else + std::cerr << message.toLocal8Bit().constData() << std::endl; + std::cerr << std::flush; +#endif + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DebugAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "DebugAppender(" + << "name:" << name() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + +} // namspace Log4Qt diff --git a/ext/Log4Qt/src/varia/debugappender.h b/ext/Log4Qt/src/varia/debugappender.h new file mode 100755 index 0000000..4df6c02 --- /dev/null +++ b/ext/Log4Qt/src/varia/debugappender.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: debugappender.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_DEBUGAPPENDER_H +#define LOG4QT_DEBUGAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DebugAppender appends logging events to the platform + * specific debug output. + * + * A DebugAppender appends to the Debugger on Windows and to stderr on all + * other systems. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT DebugAppender : public AppenderSkeleton + { + Q_OBJECT + + public: + /*! + * Creates a DebugAppender. + */ + DebugAppender(QObject *pParent = 0); + + /*! + * Creates a DebugAppender with the specified layout \a pLayout + */ + DebugAppender(Layout *pLayout, + QObject *pParent = 0); + + // virtual ~DebugAppender(); // Use compiler default + private: + DebugAppender(const DebugAppender &rOther); // Not implemented + DebugAppender &operator=(const DebugAppender &rOther); // Not implemented + + public: + /*! + * The DebugAppended requires a layout. The function returns true. + * + * \sa setLayout() + */ + virtual bool requiresLayout() const; + + protected: + /*! + * Appends the specified logging event \a rEvent to the debug output. + * The output is formatted using the appender's layout. + * + * The method is called by the AppenderSkeleton::doAppend() after it + * the entry conditions have been tested and it has been found that the + * logging event needs to be appended. + * + * \sa setLayout(), AppenderSkeleton::doAppend(), checkEntryConditions() + */ + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %DebugAppender(name:"DA" filter:0x3bee6b8 isactive:true isclosed:false + * layout:"SL" referencecount:1 threshold:"NULL") + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline DebugAppender::DebugAppender(QObject *pParent) : + AppenderSkeleton(pParent) + {} + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DebugAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_DEBUGAPPENDER_H diff --git a/ext/Log4Qt/src/varia/denyallfilter.cpp b/ext/Log4Qt/src/varia/denyallfilter.cpp new file mode 100755 index 0000000..2a7bd1f --- /dev/null +++ b/ext/Log4Qt/src/varia/denyallfilter.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.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 "varia/denyallfilter.h" + +#include <QtCore/QDebug> + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + +#ifndef QT_NO_DEBUG_STREAM + QDebug DenyAllFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "DenyAllFilter(" + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/varia/denyallfilter.h b/ext/Log4Qt/src/varia/denyallfilter.h new file mode 100755 index 0000000..2106542 --- /dev/null +++ b/ext/Log4Qt/src/varia/denyallfilter.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: denyallfilter.h + * created: September 2007 + * author: Martin Heinrich + * + * + * changes Feb 2009, Martin Heinrich + * - Fixed a compile error on VS 2008 by using Q_UNUSED(&rEvent) + * instead of Q_UNUSED(rEvent) + * + * + * 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_DENYALLFILTER_H +#define LOG4QT_DENYALLFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class DenyAllFilter drops all logging events + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT DenyAllFilter : public Filter + { + Q_OBJECT + + public: + DenyAllFilter(QObject *pParent = 0); + // DenyAllFilter(const DenyAllFilter &rOther); // Use compiler default + // virtual ~DenyAllFilter(); // Use compiler default + // DenyAllFilter &operator=(const DenyAllFilter &rOther); // Use compiler default + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %DenyAllFilter(next:QObject(0x0) referencecount:1 ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + }; + + + /************************************************************************* + * Operators, Helper + *************************************************************************/ + + + /************************************************************************* + * Inline + *************************************************************************/ + + inline DenyAllFilter::DenyAllFilter(QObject *pParent) : + Filter(pParent) + {} + + inline Filter::Decision DenyAllFilter::decide(const LoggingEvent &rEvent) const + { Q_UNUSED(&rEvent); return Filter::DENY; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::DenyAllFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_DENYALLFILTER_H diff --git a/ext/Log4Qt/src/varia/levelmatchfilter.cpp b/ext/Log4Qt/src/varia/levelmatchfilter.cpp new file mode 100755 index 0000000..6b5a815 --- /dev/null +++ b/ext/Log4Qt/src/varia/levelmatchfilter.cpp @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.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 "varia/levelmatchfilter.h" + +#include <QtCore/QDebug> +#include "loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + LevelMatchFilter::LevelMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelToMatch(Level::NULL_INT) + {} + + + Filter::Decision LevelMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (mLevelToMatch == Level::NULL_INT || + rEvent.level() != mLevelToMatch) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug LevelMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "LevelMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "leveltomatch:" << mLevelToMatch.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/varia/levelmatchfilter.h b/ext/Log4Qt/src/varia/levelmatchfilter.h new file mode 100755 index 0000000..f74c64b --- /dev/null +++ b/ext/Log4Qt/src/varia/levelmatchfilter.h @@ -0,0 +1,137 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelmatchfilter.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_LEVELMATCHFILTER_H +#define LOG4QT_LEVELMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "spi/filter.h" + +#include "level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with a specified + * level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT LevelMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), setAcceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the level to match for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelToMatch(), setLevelToMatch() + */ + Q_PROPERTY(Log4Qt::Level levelToMatch READ levelToMatch WRITE setLevelToMatch) + + public: + LevelMatchFilter(QObject *pParent = 0); + // LevelMatchFilter(const LevelMatchFilter &rOther); // Use compiler default + // virtual ~LevelMatchFilter(); // Use compiler default + // LevelMatchFilter &operator=(const LevelMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelToMatch() const; + void setAcceptOnMatch(bool accept); + void setLevelToMatch(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %LevelMatchFilter(acceptonmatch:true leveltomatch:"WARN" + * next:Log4Qt::DenyAllFilter(0x3bce3a8) + * referencecount:1 ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + Level mLevelToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelMatchFilter::levelToMatch() const + { return mLevelToMatch; } + + inline void LevelMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelMatchFilter::setLevelToMatch(Level level) + { mLevelToMatch = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELMATCHFILTER_H diff --git a/ext/Log4Qt/src/varia/levelrangefilter.cpp b/ext/Log4Qt/src/varia/levelrangefilter.cpp new file mode 100755 index 0000000..73f42c5 --- /dev/null +++ b/ext/Log4Qt/src/varia/levelrangefilter.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.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 "varia/levelrangefilter.h" + +#include <QtCore/QDebug> +#include "loggingevent.h" + + +namespace Log4Qt +{ + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + + + +/****************************************************************************** + * C helper functions + ******************************************************************************/ + + + +/****************************************************************************** + * Class implementation: Filter + ******************************************************************************/ + + +LevelRangeFilter::LevelRangeFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mLevelMin(Level::NULL_INT), + mLevelMax(Level::OFF_INT) +{} + + +Filter::Decision LevelRangeFilter::decide(const LoggingEvent &rEvent) const +{ + if (rEvent.level() < mLevelMin) + return Filter::DENY; + + if (rEvent.level() > mLevelMax) + return Filter::DENY; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::NEUTRAL; +} + + +#ifndef QT_NO_DEBUG_STREAM +QDebug LevelRangeFilter::debug(QDebug &rDebug) const +{ + rDebug.nospace() << "LevelRangeFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "levelmin:" << mLevelMin.toString() << " " + << "levelmax:" << mLevelMax.toString() << " " + << "next:" << next() + << "referencecount:" << referenceCount() << " " + << ")"; + return rDebug.space(); +} +#endif // QT_NO_DEBUG_STREAM + + + +/****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/varia/levelrangefilter.h b/ext/Log4Qt/src/varia/levelrangefilter.h new file mode 100755 index 0000000..e148d9c --- /dev/null +++ b/ext/Log4Qt/src/varia/levelrangefilter.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: levelrangefilter.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_LEVELRANGEFILTER_H +#define LOG4QT_LEVELRANGEFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "spi/filter.h" + +#include "level.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class LevelMatchFilter allows logging events with levels in a + * specified range. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT LevelRangeFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the maximum level of the range for this filter. + * + * The default is Level::OFF_INT. + * + * \sa levelMax(), setLevelMax() + */ + Q_PROPERTY(Log4Qt::Level levelMax READ levelMax WRITE setLevelMax) + + /*! + * The property holds the minimum level of the range for this filter. + * + * The default is Level::NULL_INT. + * + * \sa levelMin(), setLevelMin() + */ + Q_PROPERTY(Log4Qt::Level levelMin READ levelMin WRITE setLevelMin) + + public: + LevelRangeFilter(QObject *pParent = 0); + // LevelRangeFilter(const LevelRangeFilter &rOther); // Use compiler default + // virtual ~LevelRangeFilter(); // Use compiler default + // LevelRangeFilter &operator=(const LevelRangeFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + Level levelMax() const; + Level levelMin() const; + void setAcceptOnMatch(bool accept); + void setLevelMax(Level level); + void setLevelMin(Level level); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: + /*! + * Writes all object member variables to the given debug stream \a rDebug + * and returns the stream. + * + * <tt> + * %LevelRangeFilter(acceptonmatch:true levelmin:"ERROR" levelmax:"FATAL" + * next:Log4Qt::LevelMatchFilter(0x3bcd960) + * referencecount:1 ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; + + private: + bool mAcceptOnMatch; + Level mLevelMin; + Level mLevelMax; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool LevelRangeFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline Level LevelRangeFilter::levelMax() const + { return mLevelMax; } + + inline Level LevelRangeFilter::levelMin() const + { return mLevelMin; } + + inline void LevelRangeFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void LevelRangeFilter::setLevelMax(Level level) + { mLevelMax = level; } + + inline void LevelRangeFilter::setLevelMin(Level level) + { mLevelMin = level; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::LevelRangeFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_LEVELRANGEFILTER_H diff --git a/ext/Log4Qt/src/varia/listappender.cpp b/ext/Log4Qt/src/varia/listappender.cpp new file mode 100755 index 0000000..6b8aa39 --- /dev/null +++ b/ext/Log4Qt/src/varia/listappender.cpp @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.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 "varia/listappender.h" + +#include <QtCore/QDebug> + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: ListAppender + **************************************************************************/ + + + ListAppender::ListAppender(QObject *pParent) : + AppenderSkeleton(pParent), + mConfiguratorList(false), + mList(), + mMaxCount(0) + { + } + + + ListAppender::~ListAppender() + { + } + + + QList<LoggingEvent> ListAppender::list() const + { + QMutexLocker locker(&mObjectGuard); + + return mList; + } + + + void ListAppender::setMaxCount(int n) + { + QMutexLocker locker(&mObjectGuard); + + if (n < 0) + { + logger()->warn("Attempt to set maximum count for appender '%1' to %2. Using zero instead", name(), n); + n = 0; + } + mMaxCount = n; + ensureMaxCount(); + } + + + QList<LoggingEvent> ListAppender::clearList() + { + QMutexLocker locker(&mObjectGuard); + + QList<LoggingEvent> result = mList; + mList.clear(); + return result; + } + + + // bool ListAppender::requiresLayout() const; + + + void ListAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "ListAppender::append()", "Lock must be held by caller") + + if ((mMaxCount <= 0) || (mList.size() < mMaxCount)) + mList << rEvent; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug ListAppender::debug(QDebug &rDebug) const + { + rDebug.nospace() << "ListAppender(" + << "name:" << name() << " " + << "count:" << list().count() << " " + << "filter:" << firstFilter() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "maxcount:" << maxCount() << " " + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + void ListAppender::ensureMaxCount() + { + // Q_ASSERT_X(, "ListAppender::ensureMaxCount()", "Lock must be held by caller") + + if (mMaxCount <= 0) + return; + + while (mList.size() > mMaxCount) + mList.removeFirst(); + } + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/varia/listappender.h b/ext/Log4Qt/src/varia/listappender.h new file mode 100755 index 0000000..f5e9df0 --- /dev/null +++ b/ext/Log4Qt/src/varia/listappender.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: listappender.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_LISTAPPENDER_H +#define LOG4QT_LISTAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" + +#include <QtCore/QList> +#include <QtCore/QMutex> +#include "loggingevent.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class ListAppender appends logging events to a list for later + * processing. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT ListAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds, if the Appender is used by a configurator. + * + * The default value is false for not being a configurator list. + * + * \sa configuratorList(), setConfiguratorList() + */ + Q_PROPERTY(bool configuratorList READ configuratorList WRITE setConfiguratorList) + + /*! + * The property holds the maximum count used by the appender. + * + * The default maximum count is -1 for unlimited. + * + * \sa maxCount(), setMaxCount() + */ + Q_PROPERTY(int maxCount READ maxCount WRITE setMaxCount) + + public: + ListAppender(QObject *pParent = 0); + virtual ~ListAppender(); + private: + ListAppender(const ListAppender &rOther); // Not implemented + ListAppender &operator=(const ListAppender &rOther); // Not implemented + + public: + /*! + * Returns true, if the appender is used by a configurator. Otherweise it returns + * false. + * + * \sa setConfiguratorList() + */ + bool configuratorList() const; + + QList<LoggingEvent> list() const; + int maxCount() const; + + /*! + * Sets that the appender is used by a configurator. If set to true, the appender + * will not be removed from a Logger when Logger::removeAllAppenders()is called. + * This way the appender can collect events raised during the configuration process. + * + * \sa configuratorList(), BasicConfigurator, PropertyConfigurator, + * ConfiguratorHelper::configureError() + */ + void setConfiguratorList(bool isConfiguratorList); + + void setMaxCount(int n); + + QList<LoggingEvent> clearList(); + virtual bool requiresLayout() const; + + protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %ListAppender(name:"LA" count:1 filter:0x41fa488 isactive:true + * isclosed:false maxcount:170 referencecount:1 + * threshold:"TRACE_SET") + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + /*! + * Ensures that the count of events is less or equal then the maxium + * count. If the list contains too many items, items are deleted from + * the begin of the list. + */ + void ensureMaxCount(); + + private: + volatile bool mConfiguratorList; + QList<LoggingEvent> mList; + volatile int mMaxCount; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool ListAppender::configuratorList() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mConfiguratorList; } + + inline int ListAppender::maxCount() const + { return mMaxCount; } + + inline void ListAppender::setConfiguratorList(bool isConfiguratorList) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mConfiguratorList = isConfiguratorList; } + + inline bool ListAppender::requiresLayout() const + { return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::ListAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_LISTAPPENDER_H diff --git a/ext/Log4Qt/src/varia/nullappender.cpp b/ext/Log4Qt/src/varia/nullappender.cpp new file mode 100755 index 0000000..ed190b6 --- /dev/null +++ b/ext/Log4Qt/src/varia/nullappender.cpp @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.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 "varia/nullappender.h" + +#include <QtCore/QDebug> +#include "layout.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: NullAppender + **************************************************************************/ + + + NullAppender::NullAppender(QObject *pParent) : + AppenderSkeleton(false, pParent) + { + } + + + NullAppender::~NullAppender() + { + close(); + } + + + void NullAppender::append(const LoggingEvent &rEvent) + { + Q_UNUSED(rEvent); + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug NullAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + + rDebug.nospace() << "NullAppender(" + << "name:" << name() << " " + << "isactive:" << isActive() << " " + << "isclosed:" << isClosed() << " " + << "layout:" << layout_name << " " + << "threshold:" << threshold().toString() << " " + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/varia/nullappender.h b/ext/Log4Qt/src/varia/nullappender.h new file mode 100755 index 0000000..102f71f --- /dev/null +++ b/ext/Log4Qt/src/varia/nullappender.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: nullappender.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_NULLAPPENDER_H +#define LOG4QT_NULLAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + +/*! + * \brief The class NullAppender ignores all requests to append. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. See + * \ref Ownership "Object ownership" for more details. + */ +class LOG4QT_EXPORT NullAppender : public AppenderSkeleton +{ + Q_OBJECT + +public: + NullAppender(QObject *pParent = 0); + virtual ~NullAppender(); +private: + NullAppender(const NullAppender &rOther); // Not implemented + NullAppender &operator=(const NullAppender &rOther); // Not implemented + +public: + virtual bool requiresLayout() const; + +protected: + virtual void append(const LoggingEvent &rEvent); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream \a rDebug and + * returns the stream. + * + * <tt> + * %NullAppender() + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM +}; + + +/****************************************************************************** + * Operators, Helper + ******************************************************************************/ + + +/****************************************************************************** + * Inline + ******************************************************************************/ + +inline bool NullAppender::requiresLayout() const +{ return false; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::NullAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_NULLAPPENDER_H diff --git a/ext/Log4Qt/src/varia/stringmatchfilter.cpp b/ext/Log4Qt/src/varia/stringmatchfilter.cpp new file mode 100755 index 0000000..cdc41d0 --- /dev/null +++ b/ext/Log4Qt/src/varia/stringmatchfilter.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.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 "varia/stringmatchfilter.h" + +#include <QtCore/QDebug> +#include "loggingevent.h" + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: Filter + **************************************************************************/ + + + StringMatchFilter::StringMatchFilter(QObject *pParent) : + Filter(pParent), + mAcceptOnMatch(true), + mStringToMatch() + {} + + + Filter::Decision StringMatchFilter::decide(const LoggingEvent &rEvent) const + { + if (rEvent.message().isEmpty() || + mStringToMatch.isEmpty() || + rEvent.message().indexOf(mStringToMatch) < 0) + return Filter::NEUTRAL; + + if (mAcceptOnMatch) + return Filter::ACCEPT; + else + return Filter::DENY; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug StringMatchFilter::debug(QDebug &rDebug) const + { + rDebug.nospace() << "StringMatchFilter(" + << "acceptonmatch:" << mAcceptOnMatch << " " + << "referencecount:" << referenceCount() << " " + << "stringtomatch:" << mStringToMatch << " " + << "next:" << next() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + + /************************************************************************** + * Implementation: Operators, Helper + **************************************************************************/ + + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/varia/stringmatchfilter.h b/ext/Log4Qt/src/varia/stringmatchfilter.h new file mode 100755 index 0000000..eb2dac4 --- /dev/null +++ b/ext/Log4Qt/src/varia/stringmatchfilter.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: stringmatchfilter.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_STRINGMATCHFILTER_H +#define LOG4QT_STRINGMATCHFILTER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "spi/filter.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +namespace Log4Qt +{ + + /*! + * \brief The class StringMatchFilter allows logging events with a + * specified level. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT StringMatchFilter : public Filter + { + Q_OBJECT + + /*! + * The property holds if an event is accpeted on a match. + * + * The default is true. + * + * \sa acceptOnMatch(), acceptOnMatch() + */ + Q_PROPERTY(bool acceptOnMatch READ acceptOnMatch WRITE setAcceptOnMatch) + + /*! + * The property holds the string to match for this filter. + * + * \sa stringToMatch(), setStringToMatch() + */ + Q_PROPERTY(QString stringToMatch READ stringToMatch WRITE setStringToMatch) + + public: + StringMatchFilter(QObject *pParent = 0); + // StringMatchFilter(const StringMatchFilter &rOther); // Use compiler default + // virtual ~StringMatchFilter(); // Use compiler default + // StringMatchFilter &operator=(const StringMatchFilter &rOther); // Use compiler default + + bool acceptOnMatch() const; + QString stringToMatch() const; + void setAcceptOnMatch(bool accept); + void setStringToMatch(const QString &rString); + + virtual Decision decide(const LoggingEvent &rEvent) const; + + protected: +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %StringMatchFilter(acceptonmatch:true referencecount:1 + * stringtomatch:"LDAP_STRONG_AUTH_REQUIRED" + * next:Log4Qt::LevelMatchFilter(0x3bdd960) ) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + private: + bool mAcceptOnMatch; + QString mStringToMatch; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline bool StringMatchFilter::acceptOnMatch() const + { return mAcceptOnMatch; } + + inline QString StringMatchFilter::stringToMatch() const + { return mStringToMatch; } + + inline void StringMatchFilter::setAcceptOnMatch(bool accept) + { mAcceptOnMatch = accept; } + + inline void StringMatchFilter::setStringToMatch(const QString &rString) + { mStringToMatch = rString; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::StringMatchFilter, Q_MOVABLE_TYPE); // Use default + + +#endif // LOG4QT_STRINGMATCHFILTER_H diff --git a/ext/Log4Qt/src/writerappender.cpp b/ext/Log4Qt/src/writerappender.cpp new file mode 100755 index 0000000..adab4b0 --- /dev/null +++ b/ext/Log4Qt/src/writerappender.cpp @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.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 "writerappender.h" + +#include <QtCore/QDebug> +#include <QtCore/QTextCodec> +#include "layout.h" +#include "loggingevent.h" + + + +namespace Log4Qt +{ + + + /************************************************************************** + * Declarations + **************************************************************************/ + + + + /************************************************************************** + * C helper functions + **************************************************************************/ + + + + /************************************************************************** + * Class implementation: WriterAppender + **************************************************************************/ + + + WriterAppender::WriterAppender(QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(0), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent) : + AppenderSkeleton(false, pParent), + mpEncoding(0), + mpWriter(pTextStream), + mImmediateFlush(true) + { + setLayout(pLayout); + } + + + WriterAppender::~WriterAppender() + { + close(); + } + + + void WriterAppender::setEncoding(QTextCodec *pEncoding) + { + QMutexLocker locker(&mObjectGuard); + + if (mpEncoding == pEncoding) + return; + + mpEncoding = pEncoding; + if (mpWriter) + { + if (mpEncoding) + mpWriter->setCodec(mpEncoding); + else + mpWriter->setCodec(QTextCodec::codecForLocale()); + } + } + + + void WriterAppender::setWriter(QTextStream *pTextStream) + { + QMutexLocker locker(&mObjectGuard); + + closeWriter(); + + mpWriter = pTextStream; + if (mpEncoding && mpWriter) + mpWriter->setCodec(mpEncoding); + writeHeader(); + } + + + void WriterAppender::activateOptions() + { + QMutexLocker locker(&mObjectGuard); + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Activation of Appender '%1' that requires writer and has no writer set"), + APPENDER_ACTIVATE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return; + } + + AppenderSkeleton::activateOptions(); + } + + + void WriterAppender::close() + { + QMutexLocker locker(&mObjectGuard); + + if (isClosed()) + return; + + AppenderSkeleton::close(); + closeWriter(); + } + + + bool WriterAppender::requiresLayout() const + { + return true; + } + + + void WriterAppender::append(const LoggingEvent &rEvent) + { + // Q_ASSERT_X(, "WriterAppender::append()", "Lock must be held by caller"); + Q_ASSERT_X(layout(), "WriterAppender::append()", "Layout must not be null"); + + QString message(layout()->format(rEvent)); + + *mpWriter << message; + if (handleIoErrors()) + return; + + if (immediateFlush()) + { + mpWriter->flush(); + if (handleIoErrors()) + return; + } + } + + + bool WriterAppender::checkEntryConditions() const + { + // Q_ASSERT_X(, "WriterAppender::checkEntryConditions()", "Lock must be held by caller") + + if (!writer()) + { + LogError e = LOG4QT_QCLASS_ERROR(QT_TR_NOOP("Use of appender '%1' without a writer set"), + APPENDER_USE_MISSING_WRITER_ERROR); + e << name(); + logger()->error(e); + return false; + } + + return AppenderSkeleton::checkEntryConditions(); + } + + + void WriterAppender::closeWriter() + { + // Q_ASSERT_X(, "WriterAppender::closeWriter()", "Lock must be held by caller") + + if (!mpWriter) + return; + + writeFooter(); + mpWriter = 0; + } + + +#ifndef QT_NO_DEBUG_STREAM + QDebug WriterAppender::debug(QDebug &rDebug) const + { + QString layout_name; + if (layout()) + layout_name = layout()->name(); + QString codec_name; + if (encoding()) + codec_name = QLatin1String(encoding()->name()); + + rDebug.nospace() << "WriterAppender(" + << "name:" << name() << " " + << "encoding:" << codec_name << " " + << "filter:" << firstFilter() + << "immediateFlush:" << immediateFlush() + << "isactive:" << isActive() + << "isclosed:" << isClosed() + << "layout:" << layout_name + << "referencecount:" << referenceCount() << " " + << "threshold:" << threshold().toString() + << "writer:" << writer() + << ")"; + return rDebug.space(); + } +#endif // QT_NO_DEBUG_STREAM + + + bool WriterAppender::handleIoErrors() const + { + return false; + } + + + void WriterAppender::writeFooter() const + { + // Q_ASSERT_X(, "WriterAppender::writeFooter()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString footer = layout()->footer(); + if (footer.isEmpty()) + return; + + *mpWriter << footer << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + void WriterAppender::writeHeader() const + { + // Q_ASSERT_X(, "WriterAppender::writeHeader()", "Lock must be held by caller") + + if (!layout() || !mpWriter) + return; + + QString header = layout()->header(); + if (header.isEmpty()) + return; + + *mpWriter << header << Layout::endOfLine(); + if (handleIoErrors()) + return; + } + + + + /****************************************************************************** + * Implementation: Operators, Helper + ******************************************************************************/ + + +} // namespace Log4Qt diff --git a/ext/Log4Qt/src/writerappender.h b/ext/Log4Qt/src/writerappender.h new file mode 100755 index 0000000..f5e3ccd --- /dev/null +++ b/ext/Log4Qt/src/writerappender.h @@ -0,0 +1,200 @@ +/****************************************************************************** + * + * package: Log4Qt + * file: writerappender.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_WRITERAPPENDER_H +#define LOG4QT_WRITERAPPENDER_H + + +/****************************************************************************** + * Dependencies + ******************************************************************************/ + +#include "appenderskeleton.h" + + +/****************************************************************************** + * Declarations + ******************************************************************************/ + +class QTextCodec; +class QTextStream; + +namespace Log4Qt +{ + + /*! + * \brief The class WriterAppender appends log events to a QTextStream. + * + * \note All the functions declared in this class are thread-safe. + * + * \note The ownership and lifetime of objects of this class are managed. + * See \ref Ownership "Object ownership" for more details. + */ + class LOG4QT_EXPORT WriterAppender : public AppenderSkeleton + { + Q_OBJECT + + /*! + * The property holds the codec the appender uses. + * + * The default is null to use the codec the writer has set. + * + * \sa encoding(), setEncoding() + */ + Q_PROPERTY(QTextCodec* encoding READ encoding WRITE setEncoding) + + /*! + * The property holds the writer the appender uses. + * + * \sa writer(), setWriter() + */ + Q_PROPERTY(QTextStream* writer READ writer WRITE setWriter) + + /*! + * The property holds, if the writer flushes after all write operations. + * + * The default is true for flushing. + * + * \sa immediateFlush(), setImmediateFlush() + */ + Q_PROPERTY(bool immediateFlush READ immediateFlush WRITE setImmediateFlush) + + public: + WriterAppender(QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QObject *pParent = 0); + WriterAppender(Layout *pLayout, + QTextStream *pTextStream, + QObject *pParent = 0); + virtual ~WriterAppender(); + private: + WriterAppender(const WriterAppender &rOther); // Not implemented + WriterAppender &operator=(const WriterAppender &rOther); // Not implemented + + public: + virtual bool requiresLayout() const; + QTextCodec *encoding() const; + bool immediateFlush() const; + QTextStream *writer() const; + + /*! + * Sets the codec used by the writer to \a pTextCoded. + * + * If a codec is set with setEncoding, it will overwrite the codec set + * in the text stream. A subsequent call with \a pTextCoded equals null + * will resets the codec to the default QTextCodec::codecForLocale(). + * + * \sa encoding(), QTextSream::setCodec(), QTextCodec::codecForLocale() + */ + void setEncoding(QTextCodec *pTextCodec); + void setImmediateFlush(bool immediateFlush); + void setWriter(QTextStream *pTextStream); + + virtual void activateOptions(); + virtual void close(); + + protected: + virtual void append(const LoggingEvent &rEvent); + + /*! + * Tests if all entry conditions for using append() in this class are + * met. + * + * If a conditions is not met, an error is logged and the function + * returns false. Otherwise the result of + * AppenderSkeleton::checkEntryConditions() is returned. + * + * The checked conditions are: + * - A writer has been set (APPENDER_USE_MISSING_WRITER_ERROR) + * + * The function is called as part of the checkEntryConditions() chain + * started by AppenderSkeleton::doAppend(). + * + * \sa AppenderSkeleton::doAppend(), + * AppenderSkeleton::checkEntryConditions() + */ + virtual bool checkEntryConditions() const; + + void closeWriter(); + +#ifndef QT_NO_DEBUG_STREAM + /*! + * Writes all object member variables to the given debug stream + * \a rDebug and returns the stream. + * + * <tt> + * %WriterAppender(name:"WA" encoding:"" immediateFlush:true + * isactive:false isclosed:false layout:"TTCC" + * referencecount:1 threshold:"NULL" + * writer:0x0) + * </tt> + * \sa QDebug, operator<<(QDebug debug, const LogObject &rLogObject ) + */ + virtual QDebug debug(QDebug &rDebug) const; +#endif // QT_NO_DEBUG_STREAM + + virtual bool handleIoErrors() const; + void writeFooter() const; + void writeHeader() const; + + private: + QTextCodec *mpEncoding; + QTextStream *mpWriter; + volatile bool mImmediateFlush; + }; + + + /************************************************************************** + * Operators, Helper + **************************************************************************/ + + + /************************************************************************** + * Inline + **************************************************************************/ + + inline QTextCodec *WriterAppender::encoding() const + { QMutexLocker locker(&mObjectGuard); + return mpEncoding; } + + inline bool WriterAppender::immediateFlush() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mImmediateFlush; } + + inline QTextStream *WriterAppender::writer() const + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + return mpWriter; } + + inline void WriterAppender::setImmediateFlush(bool immediateFlush) + { // QMutexLocker locker(&mObjectGuard); // Read/Write of int is safe + mImmediateFlush = immediateFlush; } + + +} // namespace Log4Qt + + +// Q_DECLARE_TYPEINFO(Log4Qt::WriterAppender, Q_COMPLEX_TYPE); // Use default + + +#endif // LOG4QT_WRITERAPPENDER_H diff --git a/ext/ext.pro b/ext/ext.pro new file mode 100644 index 0000000..4ab8424 --- /dev/null +++ b/ext/ext.pro @@ -0,0 +1,9 @@ +# Such a project structure allowed for integrating Log4Qt via git subtree +# Log4Qt folder is pulled right from the remote repository +TEMPLATE = subdirs +SUBDIRS = Log4Qt + +lib.files += $$OUT_PWD/../../ext/Log4Qt/*.s* +lib.path = /usr/share/$$TARGET/lib + +INSTALLS += lib diff --git a/log4qt-debug.conf b/log4qt-debug.conf new file mode 100644 index 0000000..52af6e1 --- /dev/null +++ b/log4qt-debug.conf @@ -0,0 +1,42 @@ +# Set root logger level. Nothing less important will ever be printed. E.g. TRACE messages will be skipped +# rootLogger will send messages coming to it further to three printing mechanisms: to console, +# syslog and file logger (all three defined below) +log4j.rootLogger=DEBUG, consolelog, syslog, filelog + +# Define a ConsoleAppender. Colors you are supposed to see on Windows only. Didn't check it myself though +# Console will print everything that gets to rootLogger, i.e. all DEBUG+ messages +log4j.appender.consolelog=org.apache.log4j.ColorConsoleAppender +# Use SimpleTimeLayout. +log4j.appender.consolelog.layout=org.apache.log4j.SimpleTimeLayout + +# Let's not overload syslog and dump only ERROR+ messages to it +# Also no need for SimpleTimeLayout here. journalctl will record timestamp anyway +log4j.appender.syslog=org.apache.log4j.SystemLogAppender +log4j.appender.syslog.layout=org.apache.log4j.SimpleLayout +log4j.appender.syslog.serviceName=journalctl +log4j.appender.syslog.threshold=ERROR + +# DailyRollingFileAppender will create a new log file every day +# .cache directory can be cleaned by anyone, but as a good developer in the production code you should +# delete too old log files yourself. For example on every app start you could delete logs that are older +# than a couple of months +log4j.appender.filelog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.filelog.layout=org.apache.log4j.SimpleTimeLayout + +# @see in main.cpp how $XDG_CACHE_HOME is replaced with full path +log4j.appender.filelog.file=$XDG_CACHE_HOME/harbour-log4qtdemo.log + +################ +# Class/logger specific thresholds now. +# Ones for which threshold is not specified will use root logger's DEBUG level +# Use stricter levels for loggers that you want to shut up +################ + +# For example Company class is so stable, you only want ERROR+ messages from it +log4j.logger.Company=ERROR +#log4j.logger.bill=WARN + +# console.log() just as qDebug() goes to logger called "Qt" and uses level DEBUG. +# So setting it to INFO would suppress +# console.log() messages +# log4j.logger.Qt=INFO diff --git a/log4qt-release.conf b/log4qt-release.conf new file mode 100644 index 0000000..0545429 --- /dev/null +++ b/log4qt-release.conf @@ -0,0 +1,41 @@ +# In release mode let's log only ERRORs and FATALs to syslog, +# to console and our own log file let's add WARNs as welll, but everything less important we will ignore completely +# +# If more logs will be wanted, user will install increasedLogging package + +# So rootLogger will pass everything WARN+ to all appenders, syslog appender will cut it to ERROR+ later +log4j.rootLogger=WARN, consolelog, syslog, filelog + +# be a ConsoleAppender. +log4j.appender.consolelog=org.apache.log4j.ColorConsoleAppender +# use SimpleTimeLayout. +log4j.appender.consolelog.layout=org.apache.log4j.SimpleTimeLayout + + +# No need for SimpleTimeLayout here. journalctl will record timestamp anyway +# Let's not overload syslog and dump only ERROR+ messages to it, m +log4j.appender.syslog=org.apache.log4j.SystemLogAppender +log4j.appender.syslog.layout=org.apache.log4j.SimpleLayout +log4j.appender.syslog.serviceName=journalctl +log4j.appender.syslog.threshold=ERROR + +log4j.appender.filelog=org.apache.log4j.DailyRollingFileAppender +log4j.appender.filelog.layout=org.apache.log4j.SimpleTimeLayout + +# @see in main.cpp how $XDG_CACHE_HOME is replaced with full path +log4j.appender.filelog.file=$XDG_CACHE_HOME/harbour-log4qtdemo.log + + +################ +# Class/logger specific thresholds now. +# Ones for which threshold is not specified will use root logger's WARN level +# Use stricter levels for loggers that you want to silence even more +################ + +# For example Company class is so stable, you only want ERROR+ messages from it +log4j.logger.Company=ERROR +# log4j.logger.bill=WARN + +# console.log() as qDebug() goes to logger called "Qt" and level DEBUG. So setting it to INFO would suppress +# console.log() messages +# log4j.logger.Qt=INFO @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS = daemon app +SUBDIRS = ext daemon app OTHER_FILES += \ rpm/pebble.spec \ rpm/pebble.yaml diff --git a/rpm/pebble.yaml b/rpm/pebble.yaml index 1b6c5a3..39c79b4 100644 --- a/rpm/pebble.yaml +++ b/rpm/pebble.yaml @@ -30,4 +30,6 @@ Files: - '%{_datadir}/icons/hicolor/86x86/apps/%{name}.png' - '%{_libdir}/systemd/user/%{name}d.service' - '%{_libdir}/systemd/user/user-session.target.wants/%{name}d.service' +- '%{_datadir}/%{name}/log4qt.conf' +- '%{_datadir}/%{name}/lib' PkgBR: [] |
