diff --git a/libs/log4cplus/AUTHORS b/libs/log4cplus/AUTHORS new file mode 100644 index 0000000..015f260 --- /dev/null +++ b/libs/log4cplus/AUTHORS @@ -0,0 +1,5 @@ +Tad E. Smith +Michael CATANZARITI +Steighton Haley +Eduardo Francos +Vaclav Haisman diff --git a/libs/log4cplus/CMakeLists.txt b/libs/log4cplus/CMakeLists.txt new file mode 100644 index 0000000..02e6955 --- /dev/null +++ b/libs/log4cplus/CMakeLists.txt @@ -0,0 +1,145 @@ + +set (log4cplus_version_major 1) +set (log4cplus_version_minor 0) +set (log4cplus_version_patch 4) +set (log4cplus_soversion 4) +set (log4cplus_postfix "") + +find_package (Threads) +message (STATUS "Threads: ${CMAKE_THREAD_LIBS_INIT}") + +set (log4cplus_headers + include/log4cplus/appender.h + include/log4cplus/config/macosx.h + include/log4cplus/config/win32.h + include/log4cplus/config.hxx + include/log4cplus/configurator.h + include/log4cplus/consoleappender.h + include/log4cplus/fileappender.h + include/log4cplus/fstreams.h + include/log4cplus/helpers/appenderattachableimpl.h + include/log4cplus/helpers/loglog.h + include/log4cplus/helpers/logloguser.h + include/log4cplus/helpers/pointer.h + include/log4cplus/helpers/property.h + include/log4cplus/helpers/sleep.h + include/log4cplus/helpers/socket.h + include/log4cplus/helpers/socketbuffer.h + include/log4cplus/helpers/stringhelper.h + include/log4cplus/helpers/syncprims.h + include/log4cplus/helpers/thread-config.h + include/log4cplus/helpers/threads.h + include/log4cplus/helpers/timehelper.h + include/log4cplus/hierarchy.h + include/log4cplus/hierarchylocker.h + include/log4cplus/layout.h + include/log4cplus/logger.h + include/log4cplus/loggingmacros.h + include/log4cplus/loglevel.h + include/log4cplus/ndc.h + include/log4cplus/nteventlogappender.h + include/log4cplus/nullappender.h + include/log4cplus/socketappender.h + include/log4cplus/spi/appenderattachable.h + include/log4cplus/spi/factory.h + include/log4cplus/spi/filter.h + include/log4cplus/spi/loggerfactory.h + include/log4cplus/spi/loggerimpl.h + include/log4cplus/spi/loggingevent.h + include/log4cplus/spi/objectregistry.h + include/log4cplus/spi/rootlogger.h + include/log4cplus/streams.h + include/log4cplus/syslogappender.h + include/log4cplus/tstring.h + include/log4cplus/version.h + include/log4cplus/win32debugappender.h + include/log4cplus/win32consoleappender.h) + + +set (log4cplus_sources + src/appender.cxx + src/appenderattachableimpl.cxx + src/configurator.cxx + src/consoleappender.cxx + src/factory.cxx + src/fileappender.cxx + src/filter.cxx + src/global-init.cxx + src/hierarchy.cxx + src/hierarchylocker.cxx + src/layout.cxx + src/logger.cxx + src/loggerimpl.cxx + src/loggingevent.cxx + src/loglevel.cxx + src/loglog.cxx + src/logloguser.cxx + src/ndc.cxx + src/nullappender.cxx + src/objectregistry.cxx + src/patternlayout.cxx + src/pointer.cxx + src/property.cxx + src/rootlogger.cxx + src/sleep.cxx + src/socket.cxx + src/socketappender.cxx + src/socketbuffer.cxx + src/stringhelper.cxx + src/syncprims.cxx + src/syslogappender.cxx + src/threads.cxx + src/timehelper.cxx + src/version.cxx) + +#message (STATUS "Type: ${UNIX}|${CYGWIN}|${WIN32}") + +# Uncomment the following line to get locale aware string conversions. +#add_definitions (-DLOG4CPLUS_WORKING_LOCALE) +add_definitions(-DLOG4CPLUS_STATIC) + +if ("${UNIX}" OR "${CYGWIN}") + set (log4cplus_sources ${log4cplus_sources} + src/socket-unix.cxx) + set (log4cplus_headers ${log4cplus_headers} + include/log4cplus/config/defines.hxx + include/log4cplus/helpers/syncprims-pthreads.h) +elseif (WIN32) + set (log4cplus_sources ${log4cplus_sources} + src/socket-win32.cxx + src/win32debugappender.cxx + src/nteventlogappender.cxx + src/win32consoleappender.cxx) + set (log4cplus_headers ${log4cplus_headers} + include/log4cplus/helpers/syncprims-win32.h) + + # Comment out the following lines if you want non-Unicode version. + #add_definitions (-DUNICODE -D_UNICODE -UMBCS -U_MBCS) + set (log4cplus_postfix "${log4cplus_postfix}U") + + #add_definitions (-DLOG4CPLUS_STATIC) + #set (log4cplus_postfix "${log4cplus_postfix}S") +endif () + +message (STATUS "Headers: ${log4cplus_headers}") +message (STATUS "Sources: ${log4cplus_sources}") + +include_directories ("include") +set (log4cplus_all_sources ${log4cplus_sources} ${log4cplus_headers}) + +add_library (log4cplus STATIC ${log4cplus_all_sources}) +#add_library (log4cplus SHARED ${log4cplus_all_sources}) +target_link_libraries (log4cplus ${CMAKE_THREAD_LIBS_INIT}) + +set_target_properties (log4cplus PROPERTIES + VERSION "${log4cplus_version_major}.${log4cplus_version_minor}" + SOVERSION "${log4cplus_soversion}" + COMPILE_FLAGS "-DINSIDE_LOG4CPLUS") +if (WIN32) + set_target_properties (log4cplus PROPERTIES + DEBUG_POSTFIX "${log4cplus_postfix}D" + RELEASE_POSTFIX "${log4cplus_postfix}" + MINSIZEREL_POSTFIX "${log4cplus_postfix}" + RELWITHDEBINFO_POSTFIX "${log4cplus_postfix}") + target_link_libraries (log4cplus ws2_32 advapi32) +endif () diff --git a/libs/log4cplus/COPYING b/libs/log4cplus/COPYING new file mode 100644 index 0000000..9e94ab8 --- /dev/null +++ b/libs/log4cplus/COPYING @@ -0,0 +1 @@ +See the LICENSE file. diff --git a/libs/log4cplus/ChangeLog b/libs/log4cplus/ChangeLog new file mode 100644 index 0000000..c528c74 --- /dev/null +++ b/libs/log4cplus/ChangeLog @@ -0,0 +1,428 @@ +Version 1.0.4 + + - Fixed bug #3101459 - TTCCLayout time is not in milliseconds since + process start by default. + - Fixed compilation of Non-Windows builds. + - Fixed various compilation and linking issues on SunOS. + +Version 1.0.4-RC11 + + - Fixed bug #3083313, deadlock because of double locking when using + ConfigurationWatchDogThread. + - Improved portability to HP-UX and aCC compiler. + - Added %b PatternLayout format specifier; it expands to file + component of file path. + - Fixed bug #3058706, compilation error on AIX in socket-unix.cxx. + - Added %b pattern layout specifier. It expands to file name + component of path name. + - Fixed bug #3034758. Fixed infinite loop in + Hierarchy::updateParents() when logger hierarchy name starts with + a dot. + - Fixed bug #3034748. Fixed infinite loop in + PatternParser::extractOption() on missing '}'. + +Version 1.0.4-RC10 + + - Fixed bug #3030133. Make Autoconf/Automake build system to respect + provided --includedir= value. + - Removed %X{N} PatternLayout format specifier for NDC with limited + depth. Replaced it with NDCMaxDepth property. + - Improved compatibility with Windows CE. + - Fixed memory leak when using POSIX threads. + - Fixed leak of mutex used to synchronize gethostbyname() calls. + - Fixed problem with how std::toupper(), std::tolower() and + std::isspace() are used in non-Unicode builds. + +Version 1.0.4-RC9 + + - Fixed compilation problem in timehelper.cxx. + - Added %X{N} PatternLayout format specifier for NDC with limited + depth. + - Added facility property to SysLogAppender. + +Version 1.0.4-RC8 + + - Always handle %s time format specifier (seconds since epoch) in + log4cplus. Detect and use clock_gettime() when available. + - Fixed compilation on OpenSolaris with Sun C++. + - Fixed compilation on OpenBSD. + - Fixed use of operator delete/delete[] in FileAppender (Patch + #3005234). + - Updated config.guess and config.sub to latest Git repository + versions. + - Added BufferSize property to FileAppender to allow control of the + appender's output buffer. + - Removed -fkeep-inline-functions from GCC flags for non-debugging + build. + +Version 1.0.4-RC7 + + - Fixed thread safety issues with gethostbyname() by using + getaddrinfo() instead, where available. + - Fixed bug #2965390 - Minor internal debugging output issue. + - Added --enable-warnings (--disable-warnings) switches to the + configure script. + - Added ReopenDelay property to FileAppender, allowing the appender + to reopen output stream after write failure. (Patch #2971315) + +Version 1.0.4-RC6 + + - Fixed bug #2945335 - MinGW/MSYS build problems. For Windows builds + the source now defaults to static library/empty LOG4CPLUS_EXPORT + macro. + - Fixed a security problem in SyslogAppender. + - Fixed bug #2955058 - Looping over properties during variables + expansion. + - Added missing dependency on log4cplus_dll project to filter_test + project. + - Added a constructor with Properties parameter to DenyAllFilter. + - Reworked Layout, Appender and Filter factories registration. + +Version 1.0.4-RC5 + + - Implemented feature request #2927416 "Add a native Win32 Console + Appender". + - Loggingserver now exits with value 2 when it cannot open + listening socket. + - Improved Doxygen documentation. + - Added PropertyConfigurator::getProperties() and + PropertyConfigurator::getPropertyFilename() functions. + - Removed LOG4CPLUS_EXPORT on SharedObjectPtr<>. + - Turned on linker optimizations for MSVC8 builds to make resulting + binaries slightly smaller. + - Added --enable-runtime-pseudo-reloc linker option for Cygwin and + Mingw. Enable --enable-auto-import linker flag also for Mingw. + +Version 1.0.4-RC4 + + - Fixed bug #2875993 - Implement connector thread for + SocketAppender. + - Improved documentation of Appenders' properties. + - Improved behaviour of DailyRollingFileAppender. + - Added x64 (AMD64) build configuration to MSVC8 project files. + - Reworked MSVC8 project files to use .vsprops files to share + project settings. + - Moved all tests into Tests project folder. + - Improved behaviour of ConfigurationWatchDogThread. + - Fixed bug #2890819 - Handle empty input in towstring_internal() + and tostring_internal(). + - Corrected VERSION and SOVERSION in CMakeLists.txt. + - Fixed thread_test compilation on AIX. + - Added missing syncprims.cxx file in log4cplus_static.vcproj. + +Version 1.0.4-RC3 + + IMPORTANT: Majority of log4cplus' source code is now licensed using + the Apache Software License 2.0. The rest is covered by two clause + BSD license. + + - Fixed bug #2747435. Implement handling of log4cplus.configDebug + configuration property. + - Fixed variables shadowing. + - Doxygen documentation improvements and fixes. + - Add %i PatternLayout format. It expands to process ID. + - Fix logging macros compilation for LOG4CPLUS_SINGLE_THREADED case. + - Fix Logger log level configuration and root Logger handling log + level handling. + +Version 1.0.4-RC2 + + - Fixed bug #2834811. Accessing index 0 of empty strings. + - Fixed bug #2834808. Memory leak in thread local storage code. + - Removed MSVC6 directory and project files. + - Update to libtool-2.2.6. + +Version 1.0.4-RC1 + + - Fixed compilation with Borland C++ Builder compiler. + - Improved CMake build system to also build tests. + - Fixed compilation and improved support for Windows CE. + - Fixed compilation and improved support for Sun Studio 11 compiler. + - Fixed use after free and improved shutdown handling in + ConfigurationWatchDogThread. + - Implement %H (FQDN) and %h (host name) PatternLayout format + specifiers. + - Fixed bug #2829604. Environment variables substitution. + +Version 1.0.3 + + - List of bugs fixed or otherwise dealt with: + + +Version 1.0.3-RC9 + + - Tweaked Doxygen docs in comments for more recent Doxygen versions. + - Fix bug #2632087. Reworked WinSock initialization to fix deadlock + in WSAStartup() on Windows Vista. + - Fixed excessive errors reported in RollingFileAppender when + renaming non-existing files. + - Fall back to DAILY schedule in DailyRollingFileAppender for + invalid schedule specification. + - Added Debug_Unicode and Release_Unicode targets to MSVC8 test + cases builds. + +Version 1.0.3-RC8 + + - Fixed SysLogAppender not being exported out of shared library + because of missing LOG4CPLUS_EXPORT. + - Fix bug #1168433. RollingFileAppender does a rename() to rename + logfile to logfile.1 etc. rename() on Windows will not overwrite + an existing file so only the first rename works. On Windows + (only), try to remove existing file first before calling rename(). + - Fix bug #2573222. License issues. Most of log4cplus is covered by + ASL 1.1. The bits that are not covered by ASL 1.1 are covered by + two clause BSD licence. Texts of both licences are in LICENCE + file. + - Fix bug #2580037. Trim leading white space before comment + character '#' and both leading and trailing white space around + both key and value (e.g. " key = value ") in property files. + - Fix bug #2594345. Loggingserver and SocketAppender message format + mismatch. + - Fixed CMake builds. + +Version 1.0.3-RC7 + + - Fix Bug #894464. Really only consider prefixes when searching for + matching properties. + - Fix compilation for combination of non-threaded and UNICODE + settings. + +Version 1.0.3-RC6 + + - Fix Bug #852513 - Reconfiguring a logger does not remove old + appenders. + - Changed log4cplus thread helpers to block all signals on POSIX + platforms to enable their handling in a dedicated thread. (See + README, chapter Notes for explanation.) + - Changed thread creation from using CreateThread() to using + _beginthreadex() to avoid leaking C and C++ runtime memory. + - Fixed convertIntegerToString() to for negative numbers. + - Fixed wrong name used in BasicConfigurator for the + ConsoleAppender. + +Version 1.0.3-RC5 + + - Add CMakeLists.txt to facilitate compilation of log4cplus on + Windows with different compilers than just the MSVC8. + - Fix compilation of Unicode enabled build without working locale. + (Patch #2429185) + +Version 1.0.3-RC4 + + - IMPORTANT: log4cplus shared library version has been bumped to + 3. The interfaces have slightly changed and 1.0.3 is not binary + compatible with 1.0.2. + + - Fix more MSVC compilation problems. + - Changed log4cplus_static.vcproj to link with DLL C/C++ run time + (MSVCR80.dll and MSVCP80.dll). + - Implemented environment variables shadowing by properties and + recursive properties expansion. + - Reworked output directories layout of MSVC8 project. Now it + produces directories of the form + "log4cplus_{static,dll}.{Release,Debug}{_Unicode,}" and + "loggingserver.{Release,Debug}{_Unicode,}". The tests directory + projects still only compile using non-Unicode release and debug + version of the library. + - For single-threaded builds, re-use single tostringstream instead + of using a new one for each LOG4CPLUS_DEBUG() etc. macros. + - Merge Win32DebugAppender from trunk. (Patches #834925 and #858128) + - Make configuration of local server for NTEventLogAppender easier + by allowing empty server parameter string. (Feature Request + #875935) + +Version 1.0.3-RC3 + + - Fix Bug #2268760 - Trailing garbage in strings produced by + Time::getFormattedTime(). + - Fixed compilation of MSVC builds. + +Version 1.0.3-RC2 + + - Fix Bug #2106949 - Compilation problem with Borland's compiler. + - Fix Bug #1717320, #1040902, #1040676 - strftime() complains about + our custom %q and %Q format specifiers with "Invalid format + directive". + - Removed safe_auto_ptr. + - Added --enable-debugging switch to configure script. It disables + optimization and turns on debugging info generation. + - Use locale and its codecvt facet in towstring()/tostring() + implementations when --with-working-locale is defined. + - Added support for GCC's -fvisibility=hidden flag where available + together with __attribute__ ((visibility("default"))). + +Version 1.0.3-RC1 + - IMPORTANT: VC6 users, VC6 is unsupported. Its standard C++ library + is too broken. The work around for VC6's std::string has been + removed from log4cplus code; it actually does not fix the problem, + it only makes it a little bit less likely to manifest. VC6 project + files are still distributed with the source but they are broken as + we have no means to update them. We strongly suggest that you + either move away from VC6 to some more modern and standard + conforming compiler (like VC8) or that you use the STLport + standard C++ library implementation instead of VC6's own. + + - Fixed various compilation issues with MSVC8. + - Added MSVC8 project files. + - Fixed compilation with GCC 4.3. + - Fixed autoconf/automake build machinery so that it is possible to + build log4cplus in separate directory. + - Updated used autoconf and automake to version 2.62 and 1.10 + respectively. + - Enabled DLL building on Cygwin. + - Fixed Bug #894623, #1178841 - Various compilation issues on + Cygwin. + - Fixed Bug #2017876 - Destruction synchronization issue. + - Fixed Bug #1831238 - Unintentional sign extension in char -> + wchar_t conversion. + - Fixed Bug #1548998 - config.h is exporting symbols that conflict + with other applications/libraries. + - Fixed Bug #898646 - Ambiguity between ::yield() and + thread::yeild() on Solaris. + - Fixed Bug #954455 - LOG4CPLUS_ macros semicolon problem. + +Version 1.0.2 (February 10, 2004) + - Added "ImmediateFlush" configuration option to log4cplus::ConsoleAppender. + - Added do while loops around the logging statements in the macros. + - Fixed Bug #875960 - "log4cplus::ConfigureAndWatchThread crash" + - Fixed Bug #992034 - "rpm[build] -ta log4cplus-1.0.1.tar.gz doesn't work" + - Fixed Bug #875724 - "ConfigureAndWatchThread and mounted file systems" + - Fixed Bug #842280 - "'Append' mode when using FileAppended from cfg file." + All FileAppenders now have the "Append" configuration option. If this is + "true" any existing files will be opened with ios::append, otherwise they + will be opened with ios::trunc. + - Fixed Bug #805203 - "%q ConversionFormat does not accept modifiers" + + +Version 1.0.1 (December 18, 2003) + - Fixed Bug #831311 - "loggingserver.cxx clientsock.read()" + - Fixed Bug #851074 - "build problem HPUX 11, gcc 3.3" + - Fixed Bug #805242 - "Crash in log4cplus::helpers::SocketBuffer::appendSize_t" + - Fixed Bug #808119 - "TRACE_METHOD not displaying file name in log" + - Fixed Bug #827804 - "UMR in ConfigurationWatchdogThread" + - Fixed Bug #851116 - "Can not build" + - Added the OFF_LOG_LEVEL and the ALL_LOG_LEVEL LogLevels. + + +Version 1.0 (September 6 2003) + - Fix Bug #96934. (fileappender.cxx would not compile in a UNICODE build) + - Fixed compilation warning in MSVC for pointer.h + + +Version 0.9.10 (August 27 2003) + - Fixed singled-threaded build compilation issues + - The DailyRollingFileAppender no longer truncates files + - The DailyRollingFileAppender now performs a "rollover" on close(). If the + "rollover file" exists, then it will be renamed according to the pattern + that is used by the RollingFileAppender class. (Thanks Philip Green for + the suggestion.) + - Some socket-unix.cxx corrections. + - Fixed the *Factory initialization so that it compile with the HP aCC + compiler. + - Corrected the getCurrentThreadName() for MacOS X and DEC. + - "make install" now installs the header files. + + +Version 0.9.9 (August 9 2003) + - Fixed many MSVC++ compilation errors (6 and 7). + - Updated the MSVC++ projects + - Modified the Time::getFormattedTime() method to increase performance + - Modified Hierarcy::getInstanceImpl() to "deep copy" Logger names. + - Corrected some of the PatternLayout documentation to work better with + doxygen. + - Some Borland C++ Builder 6 fixes. + + +Version 0.9.8 (August 3 2003) + - Changed the LogLog class so that it is now reference counted. + - Restored the LOG4CPLUS_*_STR logging macros. + - Added support to disable the ERROR and FATAL macros by defining + LOG4CPLUS_DISABLE_* + - API Change: The LOG4CPLUS_TRACE macro now has behavior similar to all of + the other logging macros. If the old behavior is desired, then the new + LOG4CPLUS_TRACE_METHOD macro should be used. + - Modified Appender class to support the "Threshold" property. + - "localtime" is now the default time in log4cplus. + - The FileAppender no longer prints out the "header" when it opens a file. + - Added the "immediateFlush" field to the FileAppender class. + - Changed the API of the LogLevelManager class. + - Initial port work done to run on MacOS X. + - Added the HierarchyLocker class + - Added the ConfigureAndWatchThread class for runtime dynamic reconfiguration. + - Added several performance enhancements to the InternalLoggingEvent class. + - Renamed the PatternLayout "Pattern" configuration option to + "ConversionPattern". + - Added 3 new tests: configandwatch_test, customloglevel_test, and + performance_test. (No MSVC projects created for these tests, yet.) + + +Version 0.9.7 (June 28 2003) + - Added the log4cplus::DailyRollingFileAppender class. + - Added the log4cplus::helper::Time class. Now log with millisecond + granularity. (microsecond granularity if the gettimeofday() function is + available.) + - Changed log4cplus::spi::InternalLoggingEvent from a POD to a class and + introduced several performance ehancements to that class. This class + can now be extended to introduce "customized" logging. + - Fixed Bug #757989 - "TraceLogger should not hold a Logger reference" + - Added TYPE_SOCKLEN_T to configure.in (checking for whether + defines `socklen_t'). + - Added the "operator!=" to log4cplus::helpers::SharedObjectPtr. + - Made changes to make the DEC CXX 6.1 compiler happy. + - Renamed the tolower and toupper methods to avoid a name collision with a + macro with the DEC CXX compiler. + - Removed "-lstdc++" from the list of libraries in all Makefiles. + + +Version 0.9.6 (June 10 2003) + - Fixed multiple compiler warnings for the MSVC++ 7 compiler + - Modified configure.in so that it can now build on Solaris. + - Modified the configure script so that it can build a single-threaded + library (--enable-threads=no) + - Added "Filtering" to Appenders. + - Fixed Bug #741515 - "LogLog is causing a core on HP". + - Fixed Bug #733944 - "logging in system/local time" + - Fixed Bug #749040 - "Use of gmtime and localtime not thread-safe" + - Fixed Bug #750232 - "Copying of Hierarchy should not be allowed" + - Added an MSVC++ project to build log4cplus as a static library. + + +Version 0.9.5 (May 19 2003) + - Removed the LOG4CPLUS_*_STR logging macros. + - Added support to disable the TRACE, DEBUG, and INFO macros by defining + LOG4CPLUS_DISABLE_* + - Added a static doConfigure() method to PropertyConfigurator and + BasicConfigurator. + - Fixed problems with the configure script on several platforms. + - Optimized single-threaded mode. + - Fixed some problems with the MSVC++ 7 compiler. + + +Version 0.9.4 (May-5-2003) + Added SocketAppender class. + Now builds loggingserver to act as a source of logging messages from a + SocketAppender. + Numerous fixes needed for various compilers. + + +Version 0.9.3 (Apr-19-2003) + Added preliminary UNICODE support. (Little testing.) Thanks Michael CATANZARITI + Now built as a shared library instead of a static library. + Add support for Microsoft Visual C++ 6.0 back in. (Multi-threaded DLL) + Added SysLogAppender class. + Added NTEventLogAppender class. (Thanks Michael CATANZARITI) + + +Version 0.9.2 (Apr-5-2003) + Major API change: Changed the name of the Category class to Logger and + replaced the Priority class with LogLevel. + Added PropertyConfigurator class. + Added BasicConfigurator class. + + +Version 0.9.1 (Mar-22-2003) + Added PatternLayout class. + + +Version 0.9.0 + Initial beta release. diff --git a/libs/log4cplus/INSTALL b/libs/log4cplus/INSTALL new file mode 100644 index 0000000..7d1c323 --- /dev/null +++ b/libs/log4cplus/INSTALL @@ -0,0 +1,365 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/libs/log4cplus/LICENSE b/libs/log4cplus/LICENSE new file mode 100644 index 0000000..e2674fd --- /dev/null +++ b/libs/log4cplus/LICENSE @@ -0,0 +1,452 @@ +Contents +======== + +1. Log4j license +2. Log4cplus license + + +1. Log4j license +================ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 1999-2005 The Apache Software Foundation + + 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. + + +2. Log4cplus license +==================== + +Each file of log4cplus source is licensed using either two clause BSD license +or Apache license 2.0. + + +2.1 Two clause BSD license +========================== + + Copyright (C) 1999-2009 Contributors to log4cplus project. + All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +2.2 Apache 2.0 license +====================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 1999-2009 Contributors to log4cplus project + + 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. diff --git a/libs/log4cplus/NEWS b/libs/log4cplus/NEWS new file mode 100644 index 0000000..5e9e6a5 --- /dev/null +++ b/libs/log4cplus/NEWS @@ -0,0 +1 @@ +See http://log4cplus.sourceforge.net/ for the latest news. diff --git a/libs/log4cplus/README b/libs/log4cplus/README new file mode 100644 index 0000000..096707a --- /dev/null +++ b/libs/log4cplus/README @@ -0,0 +1,105 @@ +Short Description +================= + +log4cplus is a simple to use C++ logging API providing thread-safe, +flexible, and arbitrarily granular control over log management and +configuration. It is modeled after the Java log4j API. + + +Latest Project Information +========================== + +The latest up-to-date information for this project can be found at +http://log4cplus.sourceforge.net. Please submit bugs, patches, +feature requests, etc. there. + + +Current Status +============== + +This library has now reached "Production" status. + + +Tested on the following platforms +================================= + +- Linux/AMD64 with GCC 4.1.2 and 4.3.2 +- FreeBSD/i386 and AMD64 with GCC 3.4.6, 4.2.1 and 4.3.3 +- Windows XP with MS Visual C++ 8.0, 9.0 and 10.0 +- OpenSolaris 5.11 with Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21, + with -library=stlport4 + + +Notes +===== + +Cygwin/MinGW +------------ + +Some version of GCC (3.4.x and probably some of 4.x series too) on +Windows (both Mingw and Cygwin) produces lots of warnings of the form +"warning: inline function 'void foo()' is declared as dllimport: +attribute ignored." This can be worked around by adding +-Wno-attributes option to GCC command. Unfortunatelly, not all +affected version of GCC have this option. + + +Threads and signals +------------------- + +log4cplus is not safe to be used from async signals' handlers. This +is a property of most threaded programmes in general. If you are +going to use log4cplus in threaded application and if you want to use +log4cplus from signal handlers then your only option is to block +signals in all threads but one that will handle all signals. On POSIX +platforms, this is possible using the sigwait() call. log4cplus +enables this approach by blocking all signals in any threads created +through its threads helpers. + + +AIX +--- + +There appears to be a reentracy problem with AIX 5.3 and xlC 8 which +can result into a deadlock condition in some curcumstances. It is +unknown whether the problem manifests with other versions of either +the OS or the compiler, too. The problem was initially reported in a +bug report #3056687 ([1]). + +The core of the problem is that IBM's/xlC's standard C++ IOStreams +implementation uses global non recursive lock to protect some of its +state. The application in the bug report was trying to do logging +using log4cplus from inside overflow() member function of a class +derived from std::streambuf class. log4cplus itself uses +std::ostringstream. This resulted into an attempt to recursivly lock +the global non recursive lock and a deadlock. + +[1] + + +Unsupported compilers +--------------------- + +log4cplus does not support too old and broken C++ compilers: + +- Visual C++ prior to 7.1 +- GCC prior to 3.2 +- All Borland/CodeGear/Embarcadero C++ compilers + + +Unsupported platforms +--------------------- + +log4cplus requires some minimal set of C and/or C++ library +functions. Some systems/platforms fail to provide these functions and +thus log4cplus cannot be supported there: + +- Windows CE - missing implementations of functions + + +License +======= + +This library is licensed under the Apache Public License 2.0 and two +clause BSD license. Please read the included LICENSE file for +details. diff --git a/libs/log4cplus/include/log4cplus/appender.h b/libs/log4cplus/include/log4cplus/appender.h new file mode 100644 index 0000000..591ec63 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/appender.h @@ -0,0 +1,212 @@ +// Module: Log4CPLUS +// File: appender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_APPENDER_HEADER_ +#define _LOG4CPLUS_APPENDER_HEADER_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace log4cplus { + + /** + * This class is used to "handle" errors encountered in an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT ErrorHandler { + public: + virtual ~ErrorHandler(); + virtual void error(const log4cplus::tstring& err) = 0; + virtual void reset() = 0; + }; + + + + class LOG4CPLUS_EXPORT OnlyOnceErrorHandler : public ErrorHandler, + protected log4cplus::helpers::LogLogUser + { + public: + // Ctor + OnlyOnceErrorHandler() : firstTime(true){} + + virtual void error(const log4cplus::tstring& err); + virtual void reset(); + + private: + bool firstTime; + }; + + + /** + * Extend this class for implementing your own strategies for printing log + * statements. + */ + class LOG4CPLUS_EXPORT Appender + : public virtual log4cplus::helpers::SharedObject + , protected log4cplus::helpers::LogLogUser + + { + public: + // Ctor + Appender(); + Appender(const log4cplus::helpers::Properties properties); + + // Dtor + virtual ~Appender(); + + void destructorImpl(); + + // Methods + /** + * Release any resources allocated within the appender such as file + * handles, network connections, etc. + * + * It is a programming error to append to a closed appender. + */ + virtual void close() = 0; + + /** + * This method performs threshold checks and invokes filters before + * delegating actual logging to the subclasses specific {@link + * #append} method. + */ + void doAppend(const log4cplus::spi::InternalLoggingEvent& event); + + /** + * Get the name of this appender. The name uniquely identifies the + * appender. + */ + virtual log4cplus::tstring getName(); + + /** + * Set the name of this appender. The name is used by other + * components to identify this appender. + */ + virtual void setName(const log4cplus::tstring& name); + + /** + * Set the {@link ErrorHandler} for this Appender. + */ + virtual void setErrorHandler(std::auto_ptr eh); + + /** + * Return the currently set {@link ErrorHandler} for this + * Appender. + */ + virtual ErrorHandler* getErrorHandler(); + + /** + * Set the layout for this appender. Note that some appenders have + * their own (fixed) layouts or do not use one. For example, the + * SocketAppender ignores the layout set here. + */ + virtual void setLayout(std::auto_ptr layout); + + /** + * Returns the layout of this appender. The value may be NULL. + * + * This class owns the returned pointer. + */ + virtual Layout* getLayout(); + + /** + * Set the filter chain on this Appender. + */ + void setFilter(log4cplus::spi::FilterPtr f) { filter = f; } + + /** + * Get the filter chain on this Appender. + */ + log4cplus::spi::FilterPtr getFilter() const { return filter; } + + /** + * Returns this appenders threshold LogLevel. See the {@link + * #setThreshold} method for the meaning of this option. + */ + LogLevel getThreshold() const { return threshold; } + + /** + * Set the threshold LogLevel. All log events with lower LogLevel + * than the threshold LogLevel are ignored by the appender. + * + * In configuration files this option is specified by setting the + * value of the Threshold option to a LogLevel + * string, such as "DEBUG", "INFO" and so on. + */ + void setThreshold(LogLevel th) { threshold = th; } + + /** + * Check whether the message LogLevel is below the appender's + * threshold. If there is no threshold set, then the return value is + * always true. + */ + bool isAsSevereAsThreshold(LogLevel ll) const { + return ((ll != NOT_SET_LOG_LEVEL) && (ll >= threshold)); + } + + protected: + // Methods + /** + * Subclasses of Appender should implement this + * method to perform actual logging. + * @see doAppend method. + */ + virtual void append(const log4cplus::spi::InternalLoggingEvent& event) = 0; + + // Data + /** The layout variable does not need to be set if the appender + * implementation has its own layout. */ + std::auto_ptr layout; + + /** Appenders are named. */ + log4cplus::tstring name; + + /** There is no LogLevel threshold filtering by default. */ + LogLevel threshold; + + /** The first filter in the filter chain. Set to null + * initially. */ + log4cplus::spi::FilterPtr filter; + + /** It is assumed and enforced that errorHandler is never null. */ + std::auto_ptr errorHandler; + + /** Is this appender closed? */ + bool closed; + }; + + /** This is a pointer to an Appender. */ + typedef helpers::SharedObjectPtr SharedAppenderPtr; + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_APPENDER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/config.h.in b/libs/log4cplus/include/log4cplus/config.h.in new file mode 100644 index 0000000..17c7877 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/config.h.in @@ -0,0 +1,230 @@ +/* include/log4cplus/config.h.in. Generated from configure.in by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `ftime' function. */ +#undef HAVE_FTIME + +/* */ +#undef HAVE_GETADDRINFO + +/* */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the `htonl' function. */ +#undef HAVE_HTONL + +/* Define to 1 if you have the `htons' function. */ +#undef HAVE_HTONS + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#undef HAVE_LIBADVAPI32 + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#undef HAVE_LIBKERNEL32 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#undef HAVE_LIBWS2_32 + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `ntohl' function. */ +#undef HAVE_NTOHL + +/* Define to 1 if you have the `ntohs' function. */ +#undef HAVE_NTOHS + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllexport) or construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* */ +#undef LOG4CPLUS_HAVE_CLOCK_GETTIME + +/* */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTIMEOFDAY + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to int if undefined. */ +#undef socklen_t + +#endif // LOG4CPLUS_CONFIG_H diff --git a/libs/log4cplus/include/log4cplus/config.hxx b/libs/log4cplus/include/log4cplus/config.hxx new file mode 100644 index 0000000..85f1649 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/config.hxx @@ -0,0 +1,50 @@ +// Copyright (C) 2009, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_CONFIG_HXX +#define LOG4CPLUS_CONFIG_HXX + + +#if defined (_WIN32) +# include +#elif (defined(__MWERKS__) && defined(__MACOS__)) +# include +#else +# include +#endif + +#if !defined(_WIN32) +# if !defined(LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_USE_PTHREADS +# endif +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_EXPORT +# else +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_IMPORT +# endif // defined (INSIDE_LOG4CPLUS) +#endif // !_WIN32 + +#include + + +#endif // LOG4CPLUS_CONFIG_HXX diff --git a/libs/log4cplus/include/log4cplus/config/defines.hxx.in b/libs/log4cplus/include/log4cplus/config/defines.hxx.in new file mode 100644 index 0000000..5bd9538 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/config/defines.hxx.in @@ -0,0 +1,113 @@ +#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX +#define LOG4CPLUS_CONFIG_DEFINES_HXX + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTIMEOFDAY + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to int if undefined. */ +#undef socklen_t + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(export) or __attribute__((export)) construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(import) or __attribute__((import)) construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the host OS provides ENAMETOOLONG errno value. */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef LOG4CPLUS_HAVE_CLOCK_GETTIME + +#endif // LOG4CPLUS_CONFIG_DEFINES_HXX diff --git a/libs/log4cplus/include/log4cplus/config/macosx.h b/libs/log4cplus/include/log4cplus/config/macosx.h new file mode 100644 index 0000000..e526ab5 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/config/macosx.h @@ -0,0 +1,25 @@ +// Module: Log4CPLUS +// File: config-macosx.h +// Created: 7/2003 +// Author: Christopher R. Bailey +// +// +// Copyright (C) Tad E. Smith All rights reserved. +// +// This software is published under the terms of the Apache Software +// License version 1.1, a copy of which has been included with this +// distribution in the LICENSE.APL file. +// + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_MACOSX_HEADER_ +#define LOG4CPLUS_CONFIG_MACOSX_HEADER_ + +#if (defined(__APPLE__) || (defined(__MWERKS__) && defined(__MACOS__))) + +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 +#define socklen_t int + +#endif // MACOSX +#endif // LOG4CPLUS_CONFIG_MACOSX_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/config/win32.h b/libs/log4cplus/include/log4cplus/config/win32.h new file mode 100644 index 0000000..f15de86 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/config/win32.h @@ -0,0 +1,96 @@ +// Module: Log4CPLUS +// File: config-win32.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_WIN32_HEADER_ +#define LOG4CPLUS_CONFIG_WIN32_HEADER_ + +#ifdef _WIN32 +#include + +#if ! defined (_WIN32_WCE) +/* Define if you have the ftime function. */ +#define LOG4CPLUS_HAVE_FTIME 1 +#define LOG4CPLUS_HAVE_ERRNO_H +#define LOG4CPLUS_HAVE_SYS_STAT_H +#endif +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_STDLIB_H + +#if defined (_WIN32_WCE) +# define LOG4CPLUS_DLLMAIN_HINSTANCE HANDLE +# undef LOG4CPLUS_HAVE_NT_EVENT_LOG +#else +# define LOG4CPLUS_DLLMAIN_HINSTANCE HINSTANCE +# define LOG4CPLUS_HAVE_NT_EVENT_LOG +# define LOG4CPLUS_HAVE_WIN32_CONSOLE +#endif + +// Enable Win32DebugAppender +#define LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING + +// log4cplus_EXPORTS is used by the CMake build system. DLL_EXPORT is +// used by the autotools build system. +#if (defined (log4cplus_EXPORTS) || defined (DLL_EXPORT)) \ + && ! defined (LOG4CPLUS_STATIC) +# undef LOG4CPLUS_BUILD_DLL +# define LOG4CPLUS_BUILD_DLL +#endif + +#if ! defined (LOG4CPLUS_BUILD_DLL) +# undef LOG4CPLUS_STATIC +# define LOG4CPLUS_STATIC +#endif + +#if defined (LOG4CPLUS_STATIC) && defined (LOG4CPLUS_BUILD_DLL) +# error LOG4CPLUS_STATIC and LOG4CPLUS_BUILD_DLL cannot be defined both. +#endif + +#if defined (LOG4CPLUS_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_EXPORT +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED +# define LOG4CPLUS_USE_WIN32_THREADS +#endif + +#if defined(_MSC_VER) + // Warning about: identifier was truncated to '255' characters in the debug information +# pragma warning( disable : 4786 ) + // Warning about: needs to have dll-interface to be used by clients of class +# pragma warning( disable : 4251 ) + +# if _MSC_VER >= 1400 && ! defined (_WIN32_WCE) +# define LOG4CPLUS_WORKING_LOCALE +# endif + +#endif + + +#endif // _WIN32 +#endif // LOG4CPLUS_CONFIG_WIN32_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/configurator.h b/libs/log4cplus/include/log4cplus/configurator.h new file mode 100644 index 0000000..62de401 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/configurator.h @@ -0,0 +1,340 @@ +// Module: Log4CPLUS +// File: configurator.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _CONFIGURATOR_HEADER_ +#define _CONFIGURATOR_HEADER_ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + + /** + * Provides configuration from an external file. See configure() for + * the expected format. + * + * All option values admit variable substitution. For + * example, if userhome environment property is set to + * /home/xyz and the File option is set to the string + * ${userhome}/test.log, then File option will be + * interpreted as the string /home/xyz/test.log. + * + * The syntax of variable substitution is similar to that of UNIX + * shells. The string between an opening "${" and + * closing "}" is interpreted as a key. Its value is + * searched in the environment properties. The corresponding value replaces + * the ${variableName} sequence. + */ + class LOG4CPLUS_EXPORT PropertyConfigurator + : protected log4cplus::helpers::LogLogUser + { + public: + enum PCFlags + { + fRecursiveExpansion = 0x0001, + fShadowEnvironment = 0x0002, + fAllowEmptyVars = 0x0004 + }; + + // ctor and dtor + PropertyConfigurator(const log4cplus::tstring& propertyFile, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(const log4cplus::helpers::Properties& props, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(log4cplus::tistream& propertyStream, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + virtual ~PropertyConfigurator(); + + /** + * This method eliminates the need to create a temporary + * PropertyConfigurator to configure log4cplus. + * It is equivalent to the following:
+ * + * PropertyConfigurator config("filename"); + * config.configure(); + * + */ + static void doConfigure(const log4cplus::tstring& configFilename, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + + /** + * Read configuration from a file. The existing configuration is + * not cleared nor reset. If you require a different behavior, + * then call {@link Hierarchy::resetConfiguration + * resetConfiguration} method before calling + * doConfigure. + * + * The configuration file consists of statements in the format + * key=value. The syntax of different configuration + * elements are discussed below. + * + *

Appender configuration

+ * + * Appender configuration syntax is: + *
+         * # For appender named appenderName, set its class.
+         * # Note: The appender name can contain dots.
+         * log4cplus.appender.appenderName=fully.qualified.name.of.appender.class
+         *
+         * # Set appender specific options.
+         * log4cplus.appender.appenderName.option1=value1
+         * ...
+         * log4cplus.appender.appenderName.optionN=valueN
+         * 
+ * + * For each named appender you can configure its {@link Layout}. The + * syntax for configuring an appender's layout is: + *
+         * log4cplus.appender.appenderName.layout=fully.qualified.name.of.layout.class
+         * log4cplus.appender.appenderName.layout.option1=value1
+         * ....
+         * log4cplus.appender.appenderName.layout.optionN=valueN
+         * 
+ * + *

Configuring loggers

+ * + * The syntax for configuring the root logger is: + *
+         * log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
+         * 
+ * + * This syntax means that an optional LogLevel value can + * be supplied followed by appender names separated by commas. + * + * The LogLevel value can consist of the string values FATAL, + * ERROR, WARN, INFO, DEBUG or a custom LogLevel value. + * + * If a LogLevel value is specified, then the root LogLevel is set + * to the corresponding LogLevel. If no LogLevel value is specified, + * then the root LogLevel remains untouched. + * + * The root logger can be assigned multiple appenders. + * + * Each appenderName (separated by commas) will be added to + * the root logger. The named appender is defined using the + * appender syntax defined above. + * + * For non-root loggers the syntax is almost the same: + *
+         * log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
+         * 
+ * + * The meaning of the optional LogLevel value is discussed above + * in relation to the root logger. In addition however, the value + * INHERITED can be specified meaning that the named logger should + * inherit its LogLevel from the logger hierarchy. + * + * By default loggers inherit their LogLevel from the + * hierarchy. However, if you set the LogLevel of a logger and + * later decide that that logger should inherit its LogLevel, then + * you should specify INHERITED as the value for the LogLevel value. + * + * Similar to the root logger syntax, each appenderName + * (separated by commas) will be attached to the named logger. + * + * See the appender + * additivity rule in the user manual for the meaning of the + * additivity flag. + * + * The user can override any of the {@link + * Hierarchy#disable} family of methods by setting the a key + * "log4cplus.disableOverride" to true or any value other + * than false. As in
log4cplus.disableOverride=true 
+ * + *

Example

+ * + * An example configuration is given below. + * + *
+         *
+         * # Set options for appender named "A1".
+         * # Appender "A1" will be a SyslogAppender
+         * log4cplus.appender.A1=log4cplus::SyslogAppender
+         *
+         * # The syslog daemon resides on www.abc.net
+         * log4cplus.appender.A1.SyslogHost=www.abc.net
+         *
+         * # A1's layout is a PatternLayout, using the conversion pattern
+         * # %r %-5p %c{2} %M.%L %x - %m\n. Thus, the log output will
+         * # include # the relative time since the start of the application in
+         * # milliseconds, followed by the LogLevel of the log request,
+         * # followed by the two rightmost components of the logger name,
+         * # followed by the callers method name, followed by the line number,
+         * # the nested disgnostic context and finally the message itself.
+         * # Refer to the documentation of {@link PatternLayout} for further information
+         * # on the syntax of the ConversionPattern key.
+         * log4cplus.appender.A1.layout=log4cplus::PatternLayout
+         * log4cplus.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
+         *
+         * # Set options for appender named "A2"
+         * # A2 should be a RollingFileAppender, with maximum file size of 10 MB
+         * # using at most one backup file. A2's layout is TTCC, using the
+         * # ISO8061 date format with context printing enabled.
+         * log4cplus.appender.A2=log4cplus::RollingFileAppender
+         * log4cplus.appender.A2.MaxFileSize=10MB
+         * log4cplus.appender.A2.MaxBackupIndex=1
+         * log4cplus.appender.A2.layout=log4cplus::TTCCLayout
+         * log4cplus.appender.A2.layout.ContextPrinting=enabled
+         * log4cplus.appender.A2.layout.DateFormat=ISO8601
+         *
+         * # Root logger set to DEBUG using the A2 appender defined above.
+         * log4cplus.rootLogger=DEBUG, A2
+         *
+         * # Logger definitions:
+         * # The SECURITY logger inherits is LogLevel from root. However, it's output
+         * # will go to A1 appender defined above. It's additivity is non-cumulative.
+         * log4cplus.logger.SECURITY=INHERIT, A1
+         * log4cplus.additivity.SECURITY=false
+         *
+         * # Only warnings or above will be logged for the logger "SECURITY.access".
+         * # Output will go to A1.
+         * log4cplus.logger.SECURITY.access=WARN
+         *
+         *
+         * # The logger "class.of.the.day" inherits its LogLevel from the
+         * # logger hierarchy.  Output will go to the appender's of the root
+         * # logger, A2 in this case.
+         * log4cplus.logger.class.of.the.day=INHERIT
+         * 
+ * + * Refer to the setOption method in each Appender and + * Layout for class specific options. + * + * Use the # character at the beginning of a line + * for comments. + */ + virtual void configure(); + + /** + * \return The return value is reference to Properties + * container of properties with the "log4cplus." + * prefix removed and references to other properties and/or + * environment variables expanded. + */ + log4cplus::helpers::Properties const & getProperties () const; + + /** + * \return The return value is a reference to log4cplus::tstring + * containing filename of properties source file. It will be + * string "UNAVAILABLE" if the PropertyConfigurator instance has been + * constructed using one of the other constructors that do not take + * filename as parameter. + */ + log4cplus::tstring const & getPropertyFilename () const; + + protected: + // Methods + void init(); // called by the ctor + void reconfigure(); + void replaceEnvironVariables(); + void configureLoggers(); + void configureLogger(log4cplus::Logger logger, const log4cplus::tstring& config); + void configureAppenders(); + void configureAdditivity(); + + virtual Logger getLogger(const log4cplus::tstring& name); + virtual void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + // Types + typedef std::map AppenderMap; + + // Data + Hierarchy& h; + log4cplus::tstring propertyFilename; + log4cplus::helpers::Properties properties; + AppenderMap appenders; + unsigned flags; + + private: + // Disable copy + PropertyConfigurator(const PropertyConfigurator&); + PropertyConfigurator& operator=(PropertyConfigurator&); + }; + + + + /** + * Use this class to quickly configure the package. For file based + * configuration see PropertyConfigurator. BasicConfigurator + * automatically attaches ConsoleAppender to + * rootLogger, with output going to standard output, + * using DEBUG LogLevel value. + */ + class LOG4CPLUS_EXPORT BasicConfigurator : public PropertyConfigurator { + public: + // ctor and dtor + BasicConfigurator(Hierarchy& h = Logger::getDefaultHierarchy()); + virtual ~BasicConfigurator(); + + /** + * This method eliminates the need to create a temporary + * BasicConfigurator object to configure log4cplus. + * It is equivalent to the following:
+ *
+         * BasicConfigurator config;
+         * config.configure();
+         * 
+ */ + static void doConfigure(Hierarchy& h = Logger::getDefaultHierarchy()); + + private: + // Disable copy + BasicConfigurator(const BasicConfigurator&); + BasicConfigurator& operator=(BasicConfigurator&); + }; + + +#if !defined(LOG4CPLUS_SINGLE_THREADED) + // Forward Declarations + class ConfigurationWatchDogThread; + + + class LOG4CPLUS_EXPORT ConfigureAndWatchThread { + public: + // ctor and dtor + ConfigureAndWatchThread(const log4cplus::tstring& propertyFile, + unsigned int millis = 60 * 1000); + virtual ~ConfigureAndWatchThread(); + + private: + // Disallow copying of instances of this class + ConfigureAndWatchThread(const ConfigureAndWatchThread&); + ConfigureAndWatchThread& operator=(const ConfigureAndWatchThread&); + + // Data + ConfigurationWatchDogThread * watchDogThread; + }; +#endif + +} // end namespace log4cplus + +#endif // _CONFIGURATOR_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/consoleappender.h b/libs/log4cplus/include/log4cplus/consoleappender.h new file mode 100644 index 0000000..b76ad95 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/consoleappender.h @@ -0,0 +1,74 @@ +// Module: Log4CPLUS +// File: consoleappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_CONSOLE_APPENDER_HEADER_ +#define _LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + +#include +#include + +namespace log4cplus { + /** + * ConsoleAppender appends log events to std::cout or + * std::cerr using a layout specified by the + * user. The default target is std::cout. + * + *

Properties

+ *
+ *
logToStdErr
+ *
When it is set true, the output stream will be + * std::cerr instead of std::cout.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
+ */ + class LOG4CPLUS_EXPORT ConsoleAppender : public Appender { + public: + // Ctors + ConsoleAppender(bool logToStdErr = false, bool immediateFlush = false); + ConsoleAppender(const log4cplus::helpers::Properties properties); + + // Dtor + ~ConsoleAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + bool logToStdErr; + /** + * Immediate flush means that the underlying output stream + * will be flushed at the end of each append operation. + */ + bool immediateFlush; + }; + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/fileappender.h b/libs/log4cplus/include/log4cplus/fileappender.h new file mode 100644 index 0000000..785f0b0 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/fileappender.h @@ -0,0 +1,237 @@ +// Module: Log4CPLUS +// File: fileappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_FILE_APPENDER_HEADER_ +#define _LOG4CPLUS_FILE_APPENDER_HEADER_ + +#include +#include +#include +#include +#include + +#if defined(__DECCXX) +# define LOG4CPLUS_OPEN_MODE_TYPE LOG4CPLUS_FSTREAM_NAMESPACE::ios::open_mode +#else +# define LOG4CPLUS_OPEN_MODE_TYPE LOG4CPLUS_FSTREAM_NAMESPACE::ios::openmode +#endif + +namespace log4cplus { + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
File
+ *
This property specifies output file name.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
Append
+ *
When it is set true, output file will be appended to + * instead of being truncated at opening.
+ * + *
ReopenDelay
+ *
This property sets a delay after which the appender will + * try to reopen log file again, after last logging failure. The + * default value is 1 second. Setting the delay to 0 makes the + * appender not to try reopening the stream. + *
+ * + *
BufferSize
+ *
Non-zero value of this property sets up buffering of output + * stream using a buffer of given size. + *
+ *
+ */ + class LOG4CPLUS_EXPORT FileAppender : public Appender { + public: + // Ctors + FileAppender(const log4cplus::tstring& filename, + LOG4CPLUS_OPEN_MODE_TYPE mode = LOG4CPLUS_FSTREAM_NAMESPACE::ios::trunc, + bool immediateFlush = true); + FileAppender(const log4cplus::helpers::Properties& properties, + LOG4CPLUS_OPEN_MODE_TYPE mode = LOG4CPLUS_FSTREAM_NAMESPACE::ios::trunc); + + // Dtor + virtual ~FileAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + void open(LOG4CPLUS_OPEN_MODE_TYPE mode); + bool reopen(); + + // Data + /** + * Immediate flush means that the underlying writer or output stream + * will be flushed at the end of each append operation. Immediate + * flush is slower but ensures that each append request is actually + * written. If immediateFlush is set to + * false, then there is a good chance that the last few + * logs events are not actually written to persistent media if and + * when the application crashes. + * + * The immediateFlush variable is set to + * true by default. + */ + bool immediateFlush; + + /** + * When any append operation fails, reopenDelay says + * for how many seconds the next attempt to re-open the log file and + * resume logging will be delayed. If reopenDelay is zero, + * each failed append operation will cause log file to be re-opened. + * By default, reopenDelay is 1 second. + */ + int reopenDelay; + + unsigned long bufferSize; + log4cplus::tchar * buffer; + + log4cplus::tofstream out; + log4cplus::tstring filename; + + log4cplus::helpers::Time reopen_time; + + private: + void init(const log4cplus::tstring& filename, + LOG4CPLUS_OPEN_MODE_TYPE mode); + + // Disallow copying of instances of this class + FileAppender(const FileAppender&); + FileAppender& operator=(const FileAppender&); + }; + + + + /** + * RollingFileAppender extends FileAppender to backup the log + * files when they reach a certain size. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
MaxFileSize
+ *
This property specifies maximal size of output file. The + * value is in bytes. It is possible to use MB and + * KB suffixes to specify the value in megabytes or + * kilobytes instead.
+ * + *
MaxBackupIndex
+ *
This property limits the number of backup output + * files; e.g. how many log.1, log.2 etc. files + * will be kept.
+ *
+ */ + class LOG4CPLUS_EXPORT RollingFileAppender : public FileAppender { + public: + // Ctors + RollingFileAppender(const log4cplus::tstring& filename, + long maxFileSize = 10*1024*1024, // 10 MB + int maxBackupIndex = 1, + bool immediateFlush = true); + RollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~RollingFileAppender(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(); + + // Data + long maxFileSize; + int maxBackupIndex; + + private: + void init(long maxFileSize, int maxBackupIndex); + }; + + + + enum DailyRollingFileSchedule { MONTHLY, WEEKLY, DAILY, + TWICE_DAILY, HOURLY, MINUTELY}; + + /** + * DailyRollingFileAppender extends {@link FileAppender} so that the + * underlying file is rolled over at a user chosen frequency. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
Schedule
+ *
This property specifies rollover schedule. The possible + * values are MONTHLY, WEEKLY, DAILY, + * TWICE_DAILY, HOURLY and + * MINUTELY.
+ * + *
MaxBackupIndex
+ *
This property limits how many backup files are kept per + * single logging period; e.g. how many log.2009-11-07.1, + * log.2009-11-07.2 etc. files are kept.
+ * + *
+ */ + class LOG4CPLUS_EXPORT DailyRollingFileAppender : public FileAppender { + public: + // Ctors + DailyRollingFileAppender(const log4cplus::tstring& filename, + DailyRollingFileSchedule schedule = DAILY, + bool immediateFlush = true, + int maxBackupIndex = 10); + DailyRollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~DailyRollingFileAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(); + log4cplus::helpers::Time calculateNextRolloverTime(const log4cplus::helpers::Time& t) const; + log4cplus::tstring getFilename(const log4cplus::helpers::Time& t) const; + + // Data + DailyRollingFileSchedule schedule; + log4cplus::tstring scheduledFilename; + log4cplus::helpers::Time nextRolloverTime; + int maxBackupIndex; + + private: + void init(DailyRollingFileSchedule schedule); + }; + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_FILE_APPENDER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/fstreams.h b/libs/log4cplus/include/log4cplus/fstreams.h new file mode 100644 index 0000000..5a25790 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/fstreams.h @@ -0,0 +1,50 @@ +// Module: Log4CPLUS +// File: fstreams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_FSTREAMS_HEADER_ +#define LOG4CPLUS_FSTREAMS_HEADER_ + +#include + +#include + +#if defined(__DECCXX) && !defined(__USE_STD_IOSTREAM) +# define LOG4CPLUS_FSTREAM_NAMESPACE +#else +# define LOG4CPLUS_FSTREAM_NAMESPACE std +#endif + + +#ifdef UNICODE + namespace log4cplus { + typedef LOG4CPLUS_FSTREAM_NAMESPACE::wofstream tofstream; + typedef LOG4CPLUS_FSTREAM_NAMESPACE::wifstream tifstream; + } +#else + namespace log4cplus { + typedef LOG4CPLUS_FSTREAM_NAMESPACE::ofstream tofstream; + typedef LOG4CPLUS_FSTREAM_NAMESPACE::ifstream tifstream; + } +#endif // UNICODE + +#endif // LOG4CPLUS_FSTREAMS_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/appenderattachableimpl.h b/libs/log4cplus/include/log4cplus/helpers/appenderattachableimpl.h new file mode 100644 index 0000000..710232e --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/appenderattachableimpl.h @@ -0,0 +1,112 @@ +// Module: Log4CPLUS +// File: appenderattachableimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ +#define _LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachableImpl + : public log4cplus::spi::AppenderAttachable, + protected log4cplus::helpers::LogLogUser + { + public: + // Data + LOG4CPLUS_MUTEX_PTR_DECLARE appender_list_mutex; + + // Ctors + AppenderAttachableImpl(); + + // Dtor + virtual ~AppenderAttachableImpl(); + + // Methods + /** + * Add an appender. If the appender is already in the list in + * won't be added again. + */ + virtual void addAppender(SharedAppenderPtr newAppender); + + /** + * Get all previously added appenders as an vectory. + */ + virtual SharedAppenderPtrList getAllAppenders(); + + /** + * Look for an attached appender named as name. + * + * Return the appender with that name if in the list. Return null + * otherwise. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders(); + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender); + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name); + + /** + * Call the doAppend method on all attached appenders. + */ + int appendLoopOnAppenders(const spi::InternalLoggingEvent& event) const; + + protected: + // Types + typedef std::vector ListType; + + // Data + /** Array of appenders. */ + ListType appenderList; + }; // end class AppenderAttachableImpl + + } // end namespace helpers +} // end namespace log4cplus + +#endif // _LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/loglog.h b/libs/log4cplus/include/log4cplus/helpers/loglog.h new file mode 100644 index 0000000..595ab9a --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/loglog.h @@ -0,0 +1,113 @@ +// Module: Log4CPLUS +// File: loglog.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HELPERS_LOGLOG +#define _LOG4CPLUS_HELPERS_LOGLOG + +#include +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This class used to output log statements from within the log4cplus package. + * + * Log4cplus components cannot make log4cplus logging calls. However, it is + * sometimes useful for the user to learn about what log4cplus is + * doing. You can enable log4cplus internal logging by defining the + * log4cplus.configDebug variable. + * + * All log4cplus internal debug calls go to cout + * where as internal error messages are sent to + * cerr. All internal messages are prepended with + * the string "log4clus: ". + */ + class LOG4CPLUS_EXPORT LogLog + : public virtual log4cplus::helpers::SharedObject + { + public: + // Static methods + /** + * Returns a reference to the LogLog singleton. + */ + static log4cplus::helpers::SharedObjectPtr getLogLog(); + + + /** + * Allows to enable/disable log4cplus internal logging. + */ + void setInternalDebugging(bool enabled); + + /** + * In quite mode no LogLog generates strictly no output, not even + * for errors. + * + * @param quietMode A true for not + */ + void setQuietMode(bool quietMode); + + /** + * This method is used to output log4cplus internal debug + * statements. Output goes to std::cout. + */ + void debug(const log4cplus::tstring& msg); + + /** + * This method is used to output log4cplus internal error + * statements. There is no way to disable error statements. + * Output goes to std::cerr. + */ + void error(const log4cplus::tstring& msg); + + /** + * This method is used to output log4cplus internal warning + * statements. There is no way to disable warning statements. + * Output goes to std::cerr. + */ + void warn(const log4cplus::tstring& msg); + + // Dtor + virtual ~LogLog(); + + // Data + LOG4CPLUS_MUTEX_PTR_DECLARE mutex; + + private: + // Data + bool debugEnabled; + bool quietMode; + + // Ctors + LogLog(); + LogLog(const LogLog&); + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // _LOG4CPLUS_HELPERS_LOGLOG + diff --git a/libs/log4cplus/include/log4cplus/helpers/logloguser.h b/libs/log4cplus/include/log4cplus/helpers/logloguser.h new file mode 100644 index 0000000..2cbcb15 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/logloguser.h @@ -0,0 +1,62 @@ +// Module: Log4CPLUS +// File: logloguser.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HELPERS_LOGLOG_USER +#define _LOG4CPLUS_HELPERS_LOGLOG_USER + +#include + + +namespace log4cplus { + namespace helpers { + // forward declarations + class LogLog; + + /** + * This class used to simplify the use of the LogLog class. Any class + * that uses the LogLog class should extend this class and retrieve + * their reference to LogLog using the method provided. + */ + class LOG4CPLUS_EXPORT LogLogUser { + public: + // ctor and dtor + LogLogUser(); + LogLogUser(const LogLogUser&); + virtual ~LogLogUser(); + + // public methods + LogLog& getLogLog() const; + + // operators + LogLogUser& operator=(const LogLogUser& rhs); + + private: + // Data + void* loglogRef; + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // _LOG4CPLUS_HELPERS_LOGLOG_USER + diff --git a/libs/log4cplus/include/log4cplus/helpers/pointer.h b/libs/log4cplus/include/log4cplus/helpers/pointer.h new file mode 100644 index 0000000..52c1989 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/pointer.h @@ -0,0 +1,160 @@ +// Module: Log4CPLUS +// File: pointer.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +// +// Note: Some of this code uses ideas from "More Effective C++" by Scott +// Myers, Addison Wesley Longmain, Inc., (c) 1996, Chapter 29, pp. 183-213 +// + +/** @file */ + +#ifndef _LOG4CPLUS_HELPERS_POINTERS_HEADER_ +#define _LOG4CPLUS_HELPERS_POINTERS_HEADER_ + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /****************************************************************************** + * Class SharedObject (from pp. 204-205) * + ******************************************************************************/ + + class LOG4CPLUS_EXPORT SharedObject + { + public: + void addReference() const; + void removeReference() const; + + protected: + // Ctor + SharedObject() + : access_mutex(LOG4CPLUS_MUTEX_CREATE) + , count(0) + { } + + SharedObject(const SharedObject&) + : access_mutex(LOG4CPLUS_MUTEX_CREATE) + , count(0) + { } + + // Dtor + virtual ~SharedObject(); + + // Operators + SharedObject& operator=(const SharedObject&) { return *this; } + + public: + LOG4CPLUS_MUTEX_PTR_DECLARE access_mutex; + + private: + mutable int count; + }; + + + /****************************************************************************** + * Template Class SharedObjectPtr (from pp. 203, 206) * + ******************************************************************************/ + template + class SharedObjectPtr + { + public: + // Ctor + explicit + SharedObjectPtr(T* realPtr = 0) + : pointee(realPtr) + { + addref (); + } + + SharedObjectPtr(const SharedObjectPtr& rhs) + : pointee(rhs.pointee) + { + addref (); + } + + // Dtor + ~SharedObjectPtr() + { + if (pointee) + pointee->removeReference(); + } + + // Operators + bool operator==(const SharedObjectPtr& rhs) const { return (pointee == rhs.pointee); } + bool operator!=(const SharedObjectPtr& rhs) const { return (pointee != rhs.pointee); } + bool operator==(const T* rhs) const { return (pointee == rhs); } + bool operator!=(const T* rhs) const { return (pointee != rhs); } + T* operator->() const {assert (pointee); return pointee; } + T& operator*() const {assert (pointee); return *pointee; } + + SharedObjectPtr& operator=(const SharedObjectPtr& rhs) + { + return this->operator = (rhs.pointee); + } + + SharedObjectPtr& operator=(T* rhs) + { + SharedObjectPtr (rhs).swap (*this); + return *this; + } + + // Methods + T* get() const { return pointee; } + + void swap (SharedObjectPtr & other) throw () + { + std::swap (pointee, other.pointee); + } + + typedef T * (SharedObjectPtr:: * unspec_bool_type) () const; + operator unspec_bool_type () const + { + return pointee ? &SharedObjectPtr::get : 0; + } + + bool operator ! () const + { + return ! pointee; + } + + private: + // Methods + void addref() const + { + if (pointee) + pointee->addReference(); + } + + // Data + T* pointee; + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // _LOG4CPLUS_HELPERS_POINTERS_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/helpers/property.h b/libs/log4cplus/include/log4cplus/helpers/property.h new file mode 100644 index 0000000..017796a --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/property.h @@ -0,0 +1,123 @@ +// Module: Log4CPLUS +// File: property.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_PROPERTY_HEADER_ +#define LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + +#include +#include +#include +#include +#include + +#if (defined(__MWERKS__) && defined(__MACOS__)) +using std::size_t; +#endif + + +namespace log4cplus { + namespace helpers { + + class LOG4CPLUS_EXPORT Properties { + public: + Properties(); + explicit Properties(log4cplus::tistream& input); + explicit Properties(const log4cplus::tstring& inputFile); + virtual ~Properties(); + + // constants + static const tchar PROPERTIES_COMMENT_CHAR; + + // methods + /** + * Tests to see if key can be found in this map. + */ + bool exists(const log4cplus::tstring& key) const { + return data.find(key) != data.end(); + } + + + /** + * Returns the number of entries in this map. + */ + size_t size() const { + return data.size(); + } + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns null if the property is not found. + */ + log4cplus::tstring getProperty(const log4cplus::tstring& key) const; + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns the default value argument if the property is + * not found. + */ + log4cplus::tstring getProperty(const log4cplus::tstring& key, + const log4cplus::tstring& defaultVal) const; + + /** + * Returns all the keys in this property list. + */ + std::vector propertyNames() const; + + /** + * Inserts value into this map indexed by key. + */ + void setProperty(const log4cplus::tstring& key, const log4cplus::tstring& value); + + /** + * Removed the property index by key from this map. + */ + bool removeProperty(const log4cplus::tstring& key); + + /** + * Returns a subset of the "properties" whose keys start with + * "prefix". The returned "properties" have "prefix" trimmed from + * their keys. + */ + Properties getPropertySubset(const log4cplus::tstring& prefix) const; + + protected: + // Types +// LOG4CPLUS_EXPIMP_TEMPLATE template class LOG4CPLUS_EXPORT std::map; + typedef std::map StringMap; + + // Methods + void init(log4cplus::tistream& input); + + // Data + StringMap data; + }; + } // end namespace helpers + +} + + +#endif // LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/sleep.h b/libs/log4cplus/include/log4cplus/helpers/sleep.h new file mode 100644 index 0000000..8dc687c --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/sleep.h @@ -0,0 +1,38 @@ +// Module: Log4CPLUS +// File: sleep.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HELPERS_SLEEP_HEADER_ +#define _LOG4CPLUS_HELPERS_SLEEP_HEADER_ + +#include + + +namespace log4cplus { + namespace helpers { + LOG4CPLUS_EXPORT void sleep(unsigned long secs, + unsigned long nanosecs = 0); + LOG4CPLUS_EXPORT void sleepmillis(unsigned long millis); + } // end namespace helpers +} // end namespace log4cplus + +#endif // _LOG4CPLUS_HELPERS_SLEEP_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/socket.h b/libs/log4cplus/include/log4cplus/helpers/socket.h new file mode 100644 index 0000000..e79f706 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/socket.h @@ -0,0 +1,128 @@ +// Module: Log4CPLUS +// File: socket.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_HEADER_ + +#include +#include +#include +#if defined(_WIN32) +#include +#endif + +namespace log4cplus { + namespace helpers { + + enum SocketState { ok, + not_opened, + bad_address, + connection_failed, + broken_pipe, + invalid_access_mode, + message_truncated + }; + +#if !defined(_WIN32) + typedef int SOCKET_TYPE; +#define INVALID_SOCKET -1 +#else + typedef SOCKET SOCKET_TYPE; +#endif + + class LOG4CPLUS_EXPORT AbstractSocket { + public: + // ctor and dtor + AbstractSocket(); + AbstractSocket(SOCKET_TYPE sock, SocketState state, int err); + AbstractSocket(const AbstractSocket&); + virtual ~AbstractSocket() = 0; + + // methods + /// Close socket + virtual void close(); + virtual bool isOpen() const; + + AbstractSocket& operator=(const AbstractSocket& rhs); + + protected: + // Methods + virtual void copy(const AbstractSocket& rhs); + + // Data + SOCKET_TYPE sock; + SocketState state; + int err; + }; + + + + /** + * This class implements client sockets (also called just "sockets"). + * A socket is an endpoint for communication between two machines. + */ + class LOG4CPLUS_EXPORT Socket : public AbstractSocket { + public: + // ctor and dtor + Socket(); + Socket(SOCKET_TYPE sock, SocketState state, int err); + Socket(const tstring& address, int port); + virtual ~Socket(); + + // methods + virtual bool read(SocketBuffer& buffer); + virtual bool write(const SocketBuffer& buffer); + }; + + + + /** + * This class implements server sockets. A server socket waits for + * requests to come in over the network. It performs some operation + * based on that request, and then possibly returns a result to the + * requester. + */ + class LOG4CPLUS_EXPORT ServerSocket : public AbstractSocket { + public: + // ctor and dtor + ServerSocket(int port); + virtual ~ServerSocket(); + + Socket accept(); + }; + + + LOG4CPLUS_EXPORT SOCKET_TYPE openSocket(unsigned short port, SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE connectSocket(const log4cplus::tstring& hostn, + unsigned short port, SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE acceptSocket(SOCKET_TYPE sock, SocketState& state); + LOG4CPLUS_EXPORT int closeSocket(SOCKET_TYPE sock); + + LOG4CPLUS_EXPORT long read(SOCKET_TYPE sock, SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, const SocketBuffer& buffer); + + LOG4CPLUS_EXPORT tstring getHostname (bool fqdn); + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/helpers/socketbuffer.h b/libs/log4cplus/include/log4cplus/helpers/socketbuffer.h new file mode 100644 index 0000000..d7ecfc0 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/socketbuffer.h @@ -0,0 +1,79 @@ +// Module: Log4CPLUS +// File: socketbuffer.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ + +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * + */ + class LOG4CPLUS_EXPORT SocketBuffer : protected log4cplus::helpers::LogLogUser + { + public: + SocketBuffer(size_t max); + SocketBuffer(const SocketBuffer& rhs); + ~SocketBuffer(); + + SocketBuffer& operator=(const SocketBuffer& rhs); + + char *getBuffer() const { return buffer; } + size_t getMaxSize() const { return maxsize; } + size_t getSize() const { return size; } + void setSize(size_t s) { size = s; } + size_t getPos() const { return pos; } + + unsigned char readByte(); + unsigned short readShort(); + unsigned int readInt(); + tstring readString(unsigned char sizeOfChar); + + void appendByte(unsigned char val); + void appendShort(unsigned short val); + void appendInt(unsigned int val); + void appendSize_t(size_t val); + void appendString(const tstring& str); + void appendBuffer(const SocketBuffer& buffer); + + private: + // Methods + void copy(const SocketBuffer& rhs); + + // Data + size_t maxsize; + size_t size; + size_t pos; + char *buffer; + }; + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/stringhelper.h b/libs/log4cplus/include/log4cplus/helpers/stringhelper.h new file mode 100644 index 0000000..8a17b6b --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/stringhelper.h @@ -0,0 +1,239 @@ +// Module: Log4CPLUS +// File: stringhelper.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ +#define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ + +#include +#include + +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * Returns s in upper case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s); + + + /** + * Returns s in lower case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s); + + + /** + * Tokenize s using c as the delimiter and + * put the resulting tokens in _result. If + * collapseTokens is false, multiple adjacent delimiters + * will result in zero length tokens. + * + * Example: + *
+         *   string s = // Set string with '.' as delimiters
+         *   list tokens;
+         *   tokenize(s, '.', back_insert_iterator >(tokens));
+         * 
+ */ + template + inline + void + tokenize(const StringType& s, typename StringType::value_type c, + OutputIter result, bool collapseTokens = true) + { + typedef typename StringType::size_type size_type; + size_type const slen = s.length(); + size_type first = 0; + size_type i = 0; + for (i=0; i < slen; ++i) + { + if (s[i] == c) + { + *result = StringType (s, first, i - first); + ++result; + if (collapseTokens) + while (i+1 < slen && s[i+1] == c) + ++i; + first = i + 1; + } + } + if (first != i) + *result = StringType (s, first, i - first); + } + + + template + struct ConvertIntegerToStringHelper; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (tchar * & it, intType & value) + { + // The sign of the result of the modulo operator is + // implementation defined. That's why we work with + // positive counterpart instead. Also, in twos + // complement arithmetic the smallest negative number + // does not have positive counterpart; the range is + // asymetric. That's why we handle the case of value + // == min() specially here. + if (value == (std::numeric_limits::min) ()) + { + intType const r = value / 10; + intType const a = (-r) * 10; + intType const mod = -(a + value); + value = -r; + + *(it - 1) = LOG4CPLUS_TEXT('0') + static_cast(mod); + --it; + } + else + value = -value; + } + }; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (tchar * &, intType &) + { + // This will never be called for unsigned types. + } + }; + + + template + inline + void + convertIntegerToString (tstring & str, intType value) + { + typedef std::numeric_limits intTypeLimits; + typedef ConvertIntegerToStringHelper HelperType; + + const size_t buffer_size + = intTypeLimits::digits10 + 2; + tchar buffer[buffer_size]; + tchar * it = &buffer[buffer_size]; + tchar const * const buf_end = it; + + if (value == 0) + { + --it; + *it = LOG4CPLUS_TEXT('0'); + } + + bool const negative = value < 0; + if (negative) + HelperType::step1 (it, value); + + for (; value != 0; --it) + { + intType mod = value % 10; + value = value / 10; + *(it - 1) = LOG4CPLUS_TEXT('0') + static_cast(mod); + } + + if (negative) + { + --it; + *it = LOG4CPLUS_TEXT('-'); + } + + str.assign (static_cast(it), buf_end); + } + + + template + inline + tstring + convertIntegerToString (intType value) + { + tstring result; + convertIntegerToString (result, value); + return result; + } + + + + /** + * This iterator can be used in place of the back_insert_iterator + * for compilers that don't have a std::basic_string class that + * has the push_back method. + */ + template + class string_append_iterator + : public std::iterator + { + public: + typedef Container container_type; + + explicit string_append_iterator(container_type & c) + : container(&c) + { } + + string_append_iterator & + operator = (const typename container_type::value_type& value) + { + *container += value; + return *this; + } + + string_append_iterator & + operator * () + { + return *this; + } + + string_append_iterator & + operator ++ () + { + return *this; + } + + string_append_iterator + operator ++ (int) + { + return *this; + } + + protected: + container_type * container; + }; + + } // namespace helpers + +} // namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/helpers/syncprims-pthreads.h b/libs/log4cplus/include/log4cplus/helpers/syncprims-pthreads.h new file mode 100644 index 0000000..8ff6ac6 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/syncprims-pthreads.h @@ -0,0 +1,307 @@ +// Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the POSIX threads. It does not contain any +//! include guards because it is only a fragment to be included by +//! syncprims.h. + +#include +#include + + +namespace log4cplus { namespace thread { + + +#define LOG4CPLUS_THROW_RTE(msg) \ + do { detail::syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0) + + +// +// +// + +struct PthreadMutexAttr +{ + PthreadMutexAttr () + { + int ret = pthread_mutexattr_init (&attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::PthreadMutexAttr"); + } + + + ~PthreadMutexAttr () + try + { + int ret = pthread_mutexattr_destroy (&attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::~PthreadMutexAttr"); + } + catch (...) + { } + + + void + set_type (Mutex::Type t) + { + int mutex_type; + switch (t) + { + case Mutex::RECURSIVE: + mutex_type = PTHREAD_MUTEX_RECURSIVE; + break; + + default: + mutex_type = PTHREAD_MUTEX_DEFAULT; + } + + int ret = pthread_mutexattr_settype (&attr, mutex_type); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::set_type"); + } + + + pthread_mutexattr_t attr; +}; + + +// +// +// + +inline +Mutex::Mutex (Mutex::Type t) +{ + PthreadMutexAttr attr; + attr.set_type (t); + + int ret = pthread_mutex_init (&mtx, &attr.attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::Mutex"); +} + + +inline +Mutex::~Mutex () +{ + int ret = pthread_mutex_destroy (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::~Mutex"); +} + + +inline +void +Mutex::lock () const +{ + int ret = pthread_mutex_lock (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::lock"); +} + + +inline +void +Mutex::unlock () const +{ + int ret = pthread_mutex_unlock (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::unlock"); +} + + +// +// +// + +inline +Semaphore::Semaphore (unsigned max, unsigned initial) +{ + unsigned const sem_value_max = +#if defined (SEM_VALUE_MAX) + SEM_VALUE_MAX +#else + std::numeric_limits::max () +#endif + ; + + unsigned const limited_max = (std::min) (max, sem_value_max); + unsigned const limited_initial = (std::min) (initial, limited_max); + int ret = sem_init (&sem, 0, limited_initial); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); +} + + +inline +Semaphore::~Semaphore () +try +{ + int ret = sem_destroy (&sem); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); +} +catch (...) +{ } + + +inline +void +Semaphore::unlock () const +{ + int ret = sem_post (&sem); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); +} + + +inline +void +Semaphore::lock () const +{ + int ret = sem_wait (&sem); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::lock"); +} + + +// +// +// + +inline +ManualResetEvent::ManualResetEvent (bool sig) + : mtx (Mutex::DEFAULT) + , sigcount (0) + , signaled (sig) +{ + int ret = pthread_cond_init (&cv, 0); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); +} + + +inline +ManualResetEvent::~ManualResetEvent () +try +{ + int ret = pthread_cond_destroy (&cv); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); +} +catch (...) +{ } + + +inline +void +ManualResetEvent::signal () const +{ + MutexGuard mguard (mtx); + + signaled = true; + sigcount += 1; + int ret = pthread_cond_broadcast (&cv); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); + +} + + +inline +void +ManualResetEvent::wait () const +{ + MutexGuard mguard (mtx); + + if (! signaled) + { + unsigned prev_count = sigcount; + do + { + int ret = pthread_cond_wait (&cv, &mtx.mtx); + if (ret != 0) + { + mguard.unlock (); + mguard.detach (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); + } + } + while (prev_count == sigcount); + } +} + + +inline +bool +ManualResetEvent::timed_wait (unsigned long msec) const +{ + MutexGuard mguard (mtx); + + if (! signaled) + { + helpers::Time const wakeup_time (helpers::Time::gettimeofday () + + helpers::Time (msec / 1000, (msec % 1000) * 1000)); + struct timespec const ts = {wakeup_time.sec (), + wakeup_time.usec () * 1000}; + unsigned prev_count = sigcount; + do + { + int ret = pthread_cond_timedwait (&cv, &mtx.mtx, &ts); + switch (ret) + { + case 0: + break; + + case ETIMEDOUT: + return false; + + default: + mguard.unlock (); + mguard.detach (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + } + } + while (prev_count == sigcount); + } + + return true; +} + + +inline +void +ManualResetEvent::reset () const +{ + MutexGuard mguard (mtx); + + signaled = false; +} + + +#undef LOG4CPLUS_THROW_RTE + + +} } // namespace log4cplus { namespace thread { diff --git a/libs/log4cplus/include/log4cplus/helpers/syncprims-win32.h b/libs/log4cplus/include/log4cplus/helpers/syncprims-win32.h new file mode 100644 index 0000000..5ffc878 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/syncprims-win32.h @@ -0,0 +1,195 @@ +// Copyright (C) 2009, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the Win32 API. It does not contain any include +//! guards because it is only a fragment to be included by +//! syncprims.h. + +namespace log4cplus { namespace thread { + + +#define LOG4CPLUS_THROW_RTE(msg) \ + do { detail::syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0) + +// +// +// + +inline +Mutex::Mutex (Mutex::Type) +{ + InitializeCriticalSection (&cs); +} + + +inline +Mutex::~Mutex () +{ + DeleteCriticalSection (&cs); +} + + +inline +void +Mutex::lock () const +{ + EnterCriticalSection (&cs); +} + + +inline +void +Mutex::unlock () const +{ + LeaveCriticalSection (&cs); +} + + +// +// +// + +inline +Semaphore::Semaphore (unsigned max, unsigned initial) +{ + sem = CreateSemaphore (0, initial, max, 0); + if (! sem) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); +} + + +inline +Semaphore::~Semaphore () +{ + try + { + if (! CloseHandle (sem)) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + } + catch (...) + { } +} + + +inline +void +Semaphore::unlock () const +{ + DWORD ret = ReleaseSemaphore (sem, 1, 0); + if (! ret) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); +} + + +inline +void +Semaphore::lock () const +{ + DWORD ret = WaitForSingleObject (sem, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("Semaphore::lock"); +} + + +// +// +// + +inline +ManualResetEvent::ManualResetEvent (bool sig) +{ + ev = CreateEvent (0, true, sig, 0); + if (! ev) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); +} + + +inline +ManualResetEvent::~ManualResetEvent () +{ + try + { + if (! CloseHandle (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); + } + catch (...) + { } +} + + +inline +void +ManualResetEvent::signal () const +{ + if (! SetEvent (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); +} + + +inline +void +ManualResetEvent::wait () const +{ + DWORD ret = WaitForSingleObject (ev, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); +} + + +inline +bool +ManualResetEvent::timed_wait (unsigned long msec) const +{ + DWORD ret = WaitForSingleObject (ev, static_cast(msec)); + switch(ret) + { + case WAIT_OBJECT_0: + return true; + + case WAIT_TIMEOUT: + return false; + + default: + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + // Silence warnings about not returning any value from function + // returning bool. + return false; + } +} + + +inline +void +ManualResetEvent::reset () const +{ + if (! ResetEvent (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::reset"); +} + + +#undef LOG4CPLUS_THROW_RTE + + +} } // namespace log4cplus { namespace thread { diff --git a/libs/log4cplus/include/log4cplus/helpers/syncprims.h b/libs/log4cplus/include/log4cplus/helpers/syncprims.h new file mode 100644 index 0000000..990b4a3 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/syncprims.h @@ -0,0 +1,237 @@ +// Copyright (C) 2009, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_H + +#include +#include +#if defined (LOG4CPLUS_USE_PTHREADS) +# include +# include +# include +# include + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# undef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# include + +#endif + + +namespace log4cplus { namespace thread { + + +namespace detail +{ + +LOG4CPLUS_EXPORT void syncprims_throw_exception (char const * const msg, + char const * const file, int line); + +} // namespace detail + + +template +class SyncGuard +{ +public: + SyncGuard (SP const &); + ~SyncGuard (); + + void lock (); + void unlock (); + void attach (SP const &); + void detach (); + +private: + SP const * sp; + + SyncGuard (SyncGuard const &); + SyncGuard & operator = (SyncGuard const &); +}; + + +class ManualResetEvent; + + +class Mutex +{ +public: + enum Type + { + DEFAULT, + RECURSIVE + }; + + explicit Mutex (Type = RECURSIVE); + ~Mutex (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable pthread_mutex_t mtx; + friend class ManualResetEvent; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + mutable CRITICAL_SECTION cs; +#endif + + Mutex (Mutex const &); + Mutex & operator = (Mutex &); +}; + + +typedef SyncGuard MutexGuard; + + +class Semaphore +{ +public: + Semaphore (unsigned max, unsigned initial); + ~Semaphore (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable sem_t sem; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE sem; +#endif + + Semaphore (Semaphore const &); + Semaphore & operator = (Semaphore const &); +}; + + +typedef SyncGuard SemaphoreGuard; + + +class ManualResetEvent +{ +public: + ManualResetEvent (bool = false); + ~ManualResetEvent (); + + void signal () const; + void wait () const; + bool timed_wait (unsigned long msec) const; + void reset () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable pthread_cond_t cv; + mutable Mutex mtx; + mutable volatile unsigned sigcount; + mutable volatile bool signaled; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE ev; +#endif + + ManualResetEvent (ManualResetEvent const &); + ManualResetEvent & operator = (ManualResetEvent const &); +}; + + +} } // namespace log4cplus { namespace thread { + + +// Include the appropriate implementations of the classes declared +// above. + +#if defined (LOG4CPLUS_USE_PTHREADS) +# include +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# include +#endif + + +namespace log4cplus { namespace thread { + + +// +// +// + +template +inline +SyncGuard::SyncGuard (SP const & m) + : sp (&m) +{ + sp->lock (); +} + + +template +inline +SyncGuard::~SyncGuard () +{ + if (sp) + sp->unlock (); +} + + +template +inline +void +SyncGuard::lock () +{ + sp->lock (); +} + + +template +inline +void +SyncGuard::unlock () +{ + sp->unlock (); +} + + +template +inline +void +SyncGuard::attach (SP const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuard::detach () +{ + sp = 0; +} + + +} } // namespace log4cplus { namespace thread { + + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_H diff --git a/libs/log4cplus/include/log4cplus/helpers/thread-config.h b/libs/log4cplus/include/log4cplus/helpers/thread-config.h new file mode 100644 index 0000000..3aa1d04 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/thread-config.h @@ -0,0 +1,143 @@ +// Module: Log4CPLUS +// File: thread-config.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ +#define LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ + + +#ifdef LOG4CPLUS_USE_PTHREADS +# include +# include +# define LOG4CPLUS_MUTEX_PTR_DECLARE pthread_mutex_t* +# define LOG4CPLUS_MUTEX_CREATE ::log4cplus::thread::createNewMutex() +# define LOG4CPLUS_MUTEX_LOCK(mutex) pthread_mutex_lock(mutex) +# define LOG4CPLUS_MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex) +# define LOG4CPLUS_MUTEX_FREE(mutex) ::log4cplus::thread::deleteMutex(mutex) +# define LOG4CPLUS_THREAD_HANDLE_TYPE pthread_t +# define LOG4CPLUS_THREAD_KEY_TYPE pthread_t +# define LOG4CPLUS_GET_CURRENT_THREAD_NAME \ + ::log4cplus::thread::getCurrentThreadName() +# define LOG4CPLUS_GET_CURRENT_THREAD pthread_self() +# define LOG4CPLUS_THREAD_LOCAL_TYPE pthread_key_t* +# define LOG4CPLUS_THREAD_LOCAL_INIT(cleanup) \ + ::log4cplus::thread::createPthreadKey(cleanup) +# define LOG4CPLUS_GET_THREAD_LOCAL_VALUE(key) pthread_getspecific(*(key)) +# define LOG4CPLUS_SET_THREAD_LOCAL_VALUE(key, value) \ + pthread_setspecific(*(key), value) +# define LOG4CPLUS_THREAD_LOCAL_CLEANUP(key) \ + do { pthread_key_t * pthkey (key); pthread_key_delete(*pthkey); \ + delete pthkey; } while(0) +namespace log4cplus { + namespace thread { + LOG4CPLUS_EXPORT LOG4CPLUS_MUTEX_PTR_DECLARE createNewMutex(); + LOG4CPLUS_EXPORT void deleteMutex(LOG4CPLUS_MUTEX_PTR_DECLARE); + LOG4CPLUS_EXPORT LOG4CPLUS_THREAD_LOCAL_TYPE createPthreadKey(void (*) (void *)); + } +} + +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) +# undef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# include + +# define LOG4CPLUS_MUTEX_PTR_DECLARE CRITICAL_SECTION* +# define LOG4CPLUS_MUTEX_CREATE ::log4cplus::thread::createNewMutex() +# define LOG4CPLUS_MUTEX_LOCK(mutex) EnterCriticalSection(mutex) +# define LOG4CPLUS_MUTEX_UNLOCK(mutex) LeaveCriticalSection(mutex) +# define LOG4CPLUS_MUTEX_FREE(mutex) ::log4cplus::thread::deleteMutex(mutex) + +# define LOG4CPLUS_THREAD_HANDLE_TYPE HANDLE +# define LOG4CPLUS_THREAD_KEY_TYPE DWORD +# define LOG4CPLUS_GET_CURRENT_THREAD GetCurrentThreadId() +# define LOG4CPLUS_GET_CURRENT_THREAD_NAME \ + ::log4cplus::thread::getCurrentThreadName() +# define LOG4CPLUS_THREAD_LOCAL_TYPE DWORD +# define LOG4CPLUS_THREAD_LOCAL_INIT(cleanup) TlsAlloc() +# define LOG4CPLUS_GET_THREAD_LOCAL_VALUE(key) TlsGetValue(key) +# define LOG4CPLUS_SET_THREAD_LOCAL_VALUE(key, value) \ + TlsSetValue(key, static_cast(value)) +# define LOG4CPLUS_THREAD_LOCAL_CLEANUP(key) TlsFree(key) +# if defined (_MSC_VER) +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR +// Comment out the following two lines if you do intend to use log4cplus.dll +// for loading using LoadLibrary(). The __declspec(thread) functionality is not +// compatible with such DLL use. For more information why is this necessary see +// . +# define LOG4CPLUS_HAVE_TLS_SUPPORT 1 +# define LOG4CPLUS_THREAD_LOCAL_VAR __declspec(thread) +# endif + + +namespace log4cplus { namespace thread { + +LOG4CPLUS_EXPORT LOG4CPLUS_MUTEX_PTR_DECLARE createNewMutex(); +LOG4CPLUS_EXPORT void deleteMutex(LOG4CPLUS_MUTEX_PTR_DECLARE); + +} } // namespace log4cplus { namespace thread { + +#elif defined(LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_MUTEX_PTR_DECLARE int* +# define LOG4CPLUS_MUTEX_CREATE NULL +# define LOG4CPLUS_MUTEX_LOCK(mutex) +# define LOG4CPLUS_MUTEX_UNLOCK(mutex) +# define LOG4CPLUS_MUTEX_FREE(mutex) +# define LOG4CPLUS_THREAD_HANDLE_TYPE void * +# define LOG4CPLUS_THREAD_KEY_TYPE int +# define LOG4CPLUS_GET_CURRENT_THREAD 1 +# define LOG4CPLUS_GET_CURRENT_THREAD_NAME \ + LOG4CPLUS_C_STR_TO_TSTRING("single") +# define LOG4CPLUS_THREAD_LOCAL_TYPE void* +# define LOG4CPLUS_THREAD_LOCAL_INIT(cleanup) NULL +# define LOG4CPLUS_GET_THREAD_LOCAL_VALUE(key) (key) +# define LOG4CPLUS_SET_THREAD_LOCAL_VALUE(key, value) \ + do { (key) = (value); } while (0) +# define LOG4CPLUS_THREAD_LOCAL_CLEANUP(key) do { (key) = NULL; } while (0) +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR + +#else +# error "You Must define a Threading model" +#endif + +/** + * @def LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX(mutex) + * Begin a block synchronized on a mutex. + * + * @see LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX + * + * @def LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX + * End a block synchronized on a mutex. + * + * @see LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX + */ +#ifndef LOG4CPLUS_SINGLE_THREADED +# define LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX(mutex) \ + do { ::log4cplus::thread::Guard _sync_guard_object(mutex); +#else +# define LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX(mutex) do { (void)(mutex); +#endif + +#define LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX } while (0) + + +#endif // LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/threads.h b/libs/log4cplus/include/log4cplus/helpers/threads.h new file mode 100644 index 0000000..ed7f3f6 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/threads.h @@ -0,0 +1,133 @@ +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_THREADS_HEADER_ +#define _LOG4CPLUS_THREADS_HEADER_ + +#include +#include +#include + + +namespace log4cplus { namespace thread { + +/** + * This is used to lock a mutex. The dtor unlocks the mutex. + */ +class Guard +{ +public: + /** "locks" mutex. */ + Guard(LOG4CPLUS_MUTEX_PTR_DECLARE mutex) + : _mutex (mutex) + { + LOG4CPLUS_MUTEX_LOCK( _mutex ); + } + + /** "unlocks" mutex. */ + ~Guard() + { + LOG4CPLUS_MUTEX_UNLOCK( _mutex ); + } + +private: + LOG4CPLUS_MUTEX_PTR_DECLARE _mutex; + + // disable copy + Guard(const Guard&); + Guard& operator=(const Guard&); +}; + + +#ifndef LOG4CPLUS_SINGLE_THREADED + +LOG4CPLUS_EXPORT void blockAllSignals(); +LOG4CPLUS_EXPORT void yield(); +LOG4CPLUS_EXPORT tstring getCurrentThreadName(); + + +struct ThreadStart; + + +/** + * There are many cross-platform C++ Threading libraries. The goal of + * this class is not to replace (or match in functionality) those + * libraries. The goal of this class is to provide a simple Threading + * class with basic functionality. + */ +class LOG4CPLUS_EXPORT AbstractThread + : public virtual log4cplus::helpers::SharedObject +{ +public: + AbstractThread(); + bool isRunning() const { return (flags & fRUNNING) != 0; } + LOG4CPLUS_THREAD_KEY_TYPE getThreadId() const; + LOG4CPLUS_THREAD_HANDLE_TYPE getThreadHandle () const; + virtual void start(); + void join (); + +protected: + // Force objects to be constructed on the heap + virtual ~AbstractThread(); + virtual void run() = 0; + +private: + enum Flags + { + fRUNNING = 0x01, + fJOINED = 0x02 + }; + + unsigned flags; + + // Friends. + friend struct ThreadStart; + +# ifdef LOG4CPLUS_USE_PTHREADS + pthread_t handle; + +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) + HANDLE handle; +# if defined (_WIN32_WCE) + DWORD thread_id; +# else + unsigned thread_id; +# endif + +# endif + + // Disallow copying of instances of this class. + AbstractThread(const AbstractThread&); + AbstractThread& operator=(const AbstractThread&); +}; + +typedef helpers::SharedObjectPtr AbstractThreadPtr; + + +#endif // LOG4CPLUS_SINGLE_THREADED + + +} } // namespace log4cplus { namespace thread { + + +#endif // _LOG4CPLUS_THREADS_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/helpers/timehelper.h b/libs/log4cplus/include/log4cplus/helpers/timehelper.h new file mode 100644 index 0000000..6800a1c --- /dev/null +++ b/libs/log4cplus/include/log4cplus/helpers/timehelper.h @@ -0,0 +1,179 @@ +// Module: Log4CPLUS +// File: timehelper.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ +#define _LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + +#include +#include + +#if defined (LOG4CPLUS_HAVE_TIME_H) +//#include +#endif + +#if ! defined (_WIN32_WCE) +//#include +#endif + + +namespace log4cplus { + +namespace helpers { + + +#if defined (_WIN32_WCE) +using ::time_t; +using ::tm; + +#else +//using std::time_t; +//using std::tm; + +#endif + + +/** + * This class represents a Epoch time with microsecond accuracy. + */ +class LOG4CPLUS_EXPORT Time { +public: + Time(); + Time(time_t tv_sec, long tv_usec); + explicit Time(time_t time); + + /** + * Returns the current time using the gettimeofday() + * method if it is available on the current platform. (Not on + * WIN32.) + */ + static Time gettimeofday(); + + // Methods + /** + * Returns seconds value. + */ + time_t sec() const { return tv_sec; } + + /** + * Returns microseconds value. + */ + long usec() const { return tv_usec; } + + /** + * Sets the seconds value. + */ + void sec(time_t s) { tv_sec = s; } + + /** + * Sets the microseconds value. + */ + void usec(long us) { tv_usec = us; } + + /** + * Sets this Time using the mktime function. + */ + time_t setTime(tm* t); + + /** + * Returns this Time as a time_t value. + */ + time_t getTime() const; + + /** + * Populates tm using the gmtime() + * function. + */ + void gmtime(tm* t) const; + + /** + * Populates tm using the localtime() + * function. + */ + void localtime(tm* t) const; + + /** + * Returns a string with a "formatted time" specified by + * fmt. It used the strftime() + * function to do this. + * + * Look at your platform's strftime() documentation + * for the formatting options available. + * + * The following additional options are provided:
+ * %q - 3 character field that provides milliseconds + * %Q - 7 character field that provides fractional + * milliseconds. + */ + log4cplus::tstring getFormattedTime(const log4cplus::tstring& fmt, + bool use_gmtime = false) const; + + // Operators + Time& operator+=(const Time& rhs); + Time& operator-=(const Time& rhs); + Time& operator/=(long rhs); + Time& operator*=(long rhs); + +private: + void build_q_value (log4cplus::tstring & q_str) const; + void build_uc_q_value (log4cplus::tstring & uc_q_str) const; + + // Data + time_t tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; + + +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator+ + (const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator- + (const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator/ + (const log4cplus::helpers::Time& lhs, + long rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator* + (const log4cplus::helpers::Time& lhs, + long rhs); + +LOG4CPLUS_EXPORT bool operator<(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT bool operator<=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); + +LOG4CPLUS_EXPORT bool operator>(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT bool operator>=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); + +LOG4CPLUS_EXPORT bool operator==(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT bool operator!=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); + +} // namespace helpers + +} // namespace log4cplus + + +#endif // _LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/hierarchy.h b/libs/log4cplus/include/log4cplus/hierarchy.h new file mode 100644 index 0000000..2e8e467 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/hierarchy.h @@ -0,0 +1,316 @@ +// Module: Log4CPLUS +// File: hierarchy.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HIERARCHY_HEADER_ +#define _LOG4CPLUS_HIERARCHY_HEADER_ + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + // Forward Declarations + class HierarchyLocker; + + /** + * This class is specialized in retrieving loggers by name and + * also maintaining the logger hierarchy. + * + * The casual user should not have to deal with this class + * directly. However, if you are in an environment where + * multiple applications run in the same process, then read on. + * + * The structure of the logger hierarchy is maintained by the + * {@link #getInstance} method. The hierarchy is such that children + * link to their parent but parents do not have any pointers to their + * children. Moreover, loggers can be instantiated in any order, in + * particular descendant before ancestor. + * + * In case a descendant is created before a particular ancestor, + * then it creates a provision node for the ancestor and adds itself + * to the provision node. Other descendants of the same ancestor add + * themselves to the previously created provision node. + */ + class LOG4CPLUS_EXPORT Hierarchy : protected log4cplus::helpers::LogLogUser { + public: + // DISABLE_OFF should be set to a value lower than all possible + // priorities. + static const LogLevel DISABLE_OFF; + static const LogLevel DISABLE_OVERRIDE; + + // Ctors + /** + * Create a new Logger hierarchy. + */ + Hierarchy(); + + // Dtor + virtual ~Hierarchy(); + + // Methods + /** + * This call will clear all logger definitions from the internal + * hashtable. Invoking this method will irrevocably mess up the + * logger hierarchy. + * + * You should really know what you are doing before + * invoking this method. + */ + virtual void clear(); + + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + virtual bool exists(const log4cplus::tstring& name); + + /** + * Similar to {@link #disable(LogLevel)} except that the LogLevel + * argument is given as a log4cplus::tstring. + */ + virtual void disable(const log4cplus::tstring& loglevelStr); + + /** + * Disable all logging requests of LogLevel equal to or + * below the ll parameter p, for + * all loggers in this hierarchy. Logging requests of + * higher LogLevel then p remain unaffected. + * + * Nevertheless, if the {@link + * BasicConfigurator#DISABLE_OVERRIDE_KEY} system property is set to + * "true" or any value other than "false", then logging requests are + * evaluated as usual, i.e. according to the Basic Selection Rule. + * + * The "disable" family of methods are there for speed. They + * allow printing methods such as debug, info, etc. to return + * immediately after an integer comparison without walking the + * logger hierarchy. In most modern computers an integer + * comparison is measured in nanoseconds where as a logger walk is + * measured in units of microseconds. + */ + virtual void disable(LogLevel ll); + + /** + * Disable all logging requests regardless of logger and LogLevel. + * This method is equivalent to calling {@link #disable} with the + * argument FATAL_LOG_LEVEL, the highest possible LogLevel. + */ + virtual void disableAll(); + + /** + * Disable all Debug logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument DEBUG_LOG_LEVEL. + */ + virtual void disableDebug(); + + /** + * Disable all Info logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument INFO_LOG_LEVEL. + */ + virtual void disableInfo(); + + /** + * Undoes the effect of calling any of {@link #disable}, {@link + * #disableAll}, {@link #disableDebug} and {@link #disableInfo} + * methods. More precisely, invoking this method sets the Logger + * class internal variable called disable to its + * default "off" value. + */ + virtual void enableAll(); + + /** + * Return a new logger instance named as the first parameter using + * the default factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated and + * then linked with its existing ancestors as well as children. + * + * @param name The name of the logger to retrieve. + */ + virtual Logger getInstance(const log4cplus::tstring& name); + + /** + * Return a new logger instance named as the first parameter using + * factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated by the + * factory parameter and linked with its existing + * ancestors as well as children. + * + * @param name The name of the logger to retrieve. + * @param factory The factory that will make the new logger instance. + */ + virtual Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Returns all the currently defined loggers in this hierarchy. + * + * The root logger is not included in the returned list. + */ + virtual LoggerList getCurrentLoggers(); + + /** + * Is the LogLevel specified by level enabled? + */ + virtual bool isDisabled(int level); + + /** + * Get the root of this hierarchy. + */ + virtual Logger getRoot() const; + + /** + * Reset all values contained in this hierarchy instance to their + * default. This removes all appenders from all loggers, sets + * the LogLevel of all non-root loggers to NOT_SET_LOG_LEVEL, + * sets their additivity flag to true and sets the LogLevel + * of the root logger to DEBUG_LOG_LEVEL. Moreover, message disabling + * is set its default "off" value. + * + * Existing loggers are not removed. They are just reset. + * + * This method should be used sparingly and with care as it will + * block all logging until it is completed.

+ */ + virtual void resetConfiguration(); + + /** + * Set the default LoggerFactory instance. + */ + virtual void setLoggerFactory(std::auto_ptr factory); + + /** + * Returns the default LoggerFactory instance. + */ + virtual spi::LoggerFactory* getLoggerFactory() { return defaultFactory.get(); } + + /** + * Shutting down a hierarchy will safely close and remove + * all appenders in all loggers including the root logger. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + virtual void shutdown(); + + private: + // Types + typedef std::vector ProvisionNode; + typedef std::map ProvisionNodeMap; + typedef std::map LoggerMap; + + // Methods + /** + * This is the implementation of the getInstance() method. + * NOTE: This method does not lock the hashtable_mutex. + */ + virtual Logger getInstanceImpl(const log4cplus::tstring& name, + spi::LoggerFactory& factory); + + /** + * This is the implementation of the getCurrentLoggers(). + * NOTE: This method does not lock the hashtable_mutex. + */ + virtual void initializeLoggerList(LoggerList& list) const; + + /** + * This method loops through all the *potential* parents of + * logger'. There 3 possible cases: + * + * 1) No entry for the potential parent of 'logger' exists + * + * We create a ProvisionNode for this potential parent and insert + * 'logger' in that provision node. + * + * 2) There is an entry of type Logger for the potential parent. + * + * The entry is 'logger's nearest existing parent. We update logger's + * parent field with this entry. We also break from the loop + * because updating our parent's parent is our parent's + * responsibility. + * + * 3) There entry is of type ProvisionNode for this potential parent. + * + * We add 'logger' to the list of children for this potential parent. + */ + void updateParents(Logger logger); + + /** + * We update the links for all the children that placed themselves + * in the provision node 'pn'. The second argument 'logger' is a + * reference for the newly created Logger, parent of all the + * children in 'pn' + * + * We loop on all the children 'c' in 'pn': + * + * If the child 'c' has been already linked to a child of + * 'logger' then there is no need to update 'c'. + * + * Otherwise, we set logger's parent field to c's parent and set + * c's parent field to logger. + */ + void updateChildren(ProvisionNode& pn, Logger logger); + + // Data + LOG4CPLUS_MUTEX_PTR_DECLARE hashtable_mutex; + std::auto_ptr defaultFactory; + ProvisionNodeMap provisionNodes; + LoggerMap loggerPtrs; + Logger root; + + int disableValue; + + bool emittedNoAppenderWarning; + bool emittedNoResourceBundleWarning; + + // Disallow copying of instances of this class + Hierarchy(const Hierarchy&); + Hierarchy& operator=(const Hierarchy&); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::HierarchyLocker; + }; + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_HIERARCHY_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/hierarchylocker.h b/libs/log4cplus/include/log4cplus/hierarchylocker.h new file mode 100644 index 0000000..6354923 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/hierarchylocker.h @@ -0,0 +1,67 @@ +// Module: Log4CPLUS +// File: hierarchylocker.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ +#define _LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + +#include + + +namespace log4cplus { + + /** + * This is used to lock a Hierarchy. The dtor unlocks the Hierarchy. + */ + class LOG4CPLUS_EXPORT HierarchyLocker { + public: + // ctor & dtor + HierarchyLocker(Hierarchy& h); + ~HierarchyLocker(); + + /** + * Calls the resetConfiguration() method on the locked Hierarchy. + */ + void resetConfiguration(); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + private: + // Data + Hierarchy& h; + log4cplus::thread::Guard hierarchyLocker; + LoggerList loggerList; + }; + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/layout.h b/libs/log4cplus/include/log4cplus/layout.h new file mode 100644 index 0000000..cb0b2dd --- /dev/null +++ b/libs/log4cplus/include/log4cplus/layout.h @@ -0,0 +1,532 @@ +// Module: Log4CPLUS +// File: Layout.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_LAYOUT_HEADER_ +#define _LOG4CPLUS_LAYOUT_HEADER_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace log4cplus { + + // Forward Declarations + namespace pattern { + class PatternConverter; + } + + + /** + * This class is used to layout strings sent to an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT Layout : protected :: log4cplus::helpers::LogLogUser { + public: + Layout() : llmCache(getLogLevelManager()) {} + Layout(const log4cplus::helpers::Properties&) + : llmCache(getLogLevelManager()) {} + virtual ~Layout() {} + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event) = 0; + protected: + LogLevelManager& llmCache; + + private: + // Disable copy + Layout(const Layout&); + Layout& operator=(Layout&); + }; + + + + /** + * SimpleLayout consists of the LogLevel of the log statement, + * followed by " - " and then the log message itself. For example, + * + *
+     *         DEBUG - Hello world
+     * 
+ * + * {@link PatternLayout} offers a much more powerful alternative. + */ + class LOG4CPLUS_EXPORT SimpleLayout : public Layout { + public: + SimpleLayout() {} + SimpleLayout(const log4cplus::helpers::Properties& properties) : Layout(properties) {} + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + SimpleLayout(const SimpleLayout&); + SimpleLayout& operator=(const SimpleLayout&); + }; + + + + /** + * TTCC layout format consists of time, thread, Logger and nested + * diagnostic context information, hence the name. + * + * The time format depends on the DateFormat used. Use the + * Use_gmtime to specify whether messages should be logged using + * localtime or gmtime. + * + * Here is an example TTCCLayout output: + * + *
+     * 176 [main] INFO  org.apache.log4j.examples.Sort - Populating an array of 2 elements in reverse order.
+     * 225 [main] INFO  org.apache.log4j.examples.SortAlgo - Entered the sort method.
+     * 262 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=1 - Outer loop.
+     * 276 [main] DEBUG org.apache.log4j.examples.SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0
+     * 290 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=0 - Outer loop.
+     * 304 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Dump of interger array:
+     * 317 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Element [0] = 0
+     * 331 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Element [1] = 1
+     * 343 [main] INFO  org.apache.log4j.examples.Sort - The next log statement should be an error message.
+     * 346 [main] ERROR org.apache.log4j.examples.SortAlgo.DUMP - Tried to dump an uninitialized array.
+     * 467 [main] INFO  org.apache.log4j.examples.Sort - Exiting main method.
+     * 
+ * + * The first field is the number of milliseconds elapsed since the + * start of the program. The second field is the thread outputting the + * log statement. The third field is the LogLevel, the fourth field is + * the logger to which the statement belongs. + * + * The fifth field (just before the '-') is the nested diagnostic + * context. Note the nested diagnostic context may be empty as in the + * first two statements. The text after the '-' is the message of the + * statement. + * + * PatternLayout offers a much more flexible alternative. + */ + class LOG4CPLUS_EXPORT TTCCLayout : public Layout { + public: + // Ctor and dtor + TTCCLayout(bool use_gmtime = false); + TTCCLayout(const log4cplus::helpers::Properties& properties); + virtual ~TTCCLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + log4cplus::tstring dateFormat; + bool use_gmtime; + + private: + // Disallow copying of instances of this class + TTCCLayout(const TTCCLayout&); + TTCCLayout& operator=(const TTCCLayout&); + }; + + + + + /** + * A flexible layout configurable with pattern string. + * + * The goal of this class is to format a InternalLoggingEvent and return + * the results as a string. The results depend on the conversion + * pattern. + * + * The conversion pattern is closely related to the conversion + * pattern of the printf function in C. A conversion pattern is + * composed of literal text and format control expressions called + * conversion specifiers. + * + * You are free to insert any literal text within the conversion + * pattern. + * + * Each conversion specifier starts with a percent sign (%%) and is + * followed by optional format modifiers and a conversion + * character. The conversion character specifies the type of + * data, e.g. Logger, LogLevel, date, thread name. The format + * modifiers control such things as field width, padding, left and + * right justification. The following is a simple example. + * + * Let the conversion pattern be "%-5p [%t]: %m%n" and assume + * that the log4cplus environment was set to use a PatternLayout. Then the + * statements + *
+     * Logger root = Logger.getRoot();
+     * LOG4CPLUS_DEBUG(root, "Message 1");
+     * LOG4CPLUS_WARN(root, "Message 2");
+     * 
+ * would yield the output + *
+     * DEBUG [main]: Message 1
+     * WARN  [main]: Message 2  
+     * 
+ * + * Note that there is no explicit separator between text and + * conversion specifiers. The pattern parser knows when it has reached + * the end of a conversion specifier when it reads a conversion + * character. In the example above the conversion specifier + * "%-5p" means the LogLevel of the logging event should be left + * justified to a width of five characters. + * + * The recognized conversion characters are + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Conversion CharacterEffect
bUsed to output file name component of path name. + * E.g. main.cxx from path ../../main.cxx.
cUsed to output the logger of the logging event. The + * logger conversion specifier can be optionally followed by + * precision specifier, that is a decimal constant in + * brackets. + * + * If a precision specifier is given, then only the corresponding + * number of right most components of the logger name will be + * printed. By default the logger name is printed in full. + * + * For example, for the logger name "a.b.c" the pattern + * %c{2} will output "b.c". + * + *
dUsed to output the date of the logging event in UTC. + * + * The date conversion specifier may be followed by a date format + * specifier enclosed between braces. For example, %%d{%%H:%%M:%%s} + * or %%d{%%d %%b %%Y %%H:%%M:%%s}. If no date format + * specifier is given then %%d{%%d %%m %%Y %%H:%%M:%%s} + * is assumed. + * + * The Following format options are possible: + *
    + *
  • %%a -- Abbreviated weekday name
  • + *
  • %%A -- Full weekday name
  • + *
  • %%b -- Abbreviated month name
  • + *
  • %%B -- Full month name
  • + *
  • %%c -- Standard date and time string
  • + *
  • %%d -- Day of month as a decimal(1-31)
  • + *
  • %%H -- Hour(0-23)
  • + *
  • %%I -- Hour(1-12)
  • + *
  • %%j -- Day of year as a decimal(1-366)
  • + *
  • %%m -- Month as decimal(1-12)
  • + *
  • %%M -- Minute as decimal(0-59)
  • + *
  • %%p -- Locale's equivalent of AM or PM
  • + *
  • %%q -- milliseconds as decimal(0-999) -- Log4CPLUS specific + *
  • %%Q -- fractional milliseconds as decimal(0-999.999) -- Log4CPLUS specific + *
  • %%S -- Second as decimal(0-59)
  • + *
  • %%U -- Week of year, Sunday being first day(0-53)
  • + *
  • %%w -- Weekday as a decimal(0-6, Sunday being 0)
  • + *
  • %%W -- Week of year, Monday being first day(0-53)
  • + *
  • %%x -- Standard date string
  • + *
  • %%X -- Standard time string
  • + *
  • %%y -- Year in decimal without century(0-99)
  • + *
  • %%Y -- Year including century as decimal
  • + *
  • %%Z -- Time zone name
  • + *
  • %% -- The percent sign
  • + *
+ * + * Lookup the documentation for the strftime() function + * found in the <ctime> header for more information. + *
DUsed to output the date of the logging event in local time. + * + * All of the above information applies. + *
FUsed to output the file name where the logging request was + * issued. + * + * NOTE Unlike log4j, there is no performance penalty for + * calling this method. + * + *
hUsed to output the hostname of this system (as returned + * by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
HUsed to output the fully-qualified domain name of this + * system (as returned by gethostbyname(2) for the hostname + * returned by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
lEquivalent to using "%F:%L" + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
LUsed to output the line number from where the logging request + * was issued. + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
mUsed to output the application supplied message associated with + * the logging event.
nOutputs the platform dependent line separator character or + * characters. + *
pUsed to output the LogLevel of the logging event.
tUsed to output the name of the thread that generated the + * logging event.
iUsed to output the process ID of the process that generated the + * logging event.
xUsed to output the NDC (nested diagnostic context) associated + * with the thread that generated the logging event. + *
"%%"The sequence "%%" outputs a single percent sign. + *
+ * + * By default the relevant information is output as is. However, + * with the aid of format modifiers it is possible to change the + * minimum field width, the maximum field width and justification. + * + * The optional format modifier is placed between the percent sign + * and the conversion character. + * + * The first optional format modifier is the left justification + * flag which is just the minus (-) character. Then comes the + * optional minimum field width modifier. This is a decimal + * constant that represents the minimum number of characters to + * output. If the data item requires fewer characters, it is padded on + * either the left or the right until the minimum width is + * reached. The default is to pad on the left (right justify) but you + * can specify right padding with the left justification flag. The + * padding character is space. If the data item is larger than the + * minimum field width, the field is expanded to accommodate the + * data. The value is never truncated. + * + * This behavior can be changed using the maximum field + * width modifier which is designated by a period followed by a + * decimal constant. If the data item is longer than the maximum + * field, then the extra characters are removed from the + * beginning of the data item and not from the end. For + * example, it the maximum field width is eight and the data item is + * ten characters long, then the first two characters of the data item + * are dropped. This behavior deviates from the printf function in C + * where truncation is done from the end. + * + * Below are various format modifier examples for the logger + * conversion specifier. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Format modifierleft justifyminimum widthmaximum widthcomment
%20cfalse20noneLeft pad with spaces if the logger name is less than 20 + * characters long. + *
%-20c true 20 none Right pad with + * spaces if the logger name is less than 20 characters long. + *
%.30cNAnone30Truncate from the beginning if the logger name is longer than 30 + * characters. + *
%20.30cfalse2030Left pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
%-20.30ctrue2030Right pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
+ * + * Below are some examples of conversion patterns. + * + *
+ * + *
"%r [%t] %-5p %c %x - %m%n" + *
This is essentially the TTCC layout. + * + *
"%-6r [%15.15t] %-5p %30.30c %x - %m%n" + * + *
Similar to the TTCC layout except that the relative time is + * right padded if less than 6 digits, thread name is right padded if + * less than 15 characters and truncated if longer and the logger + * name is left padded if shorter than 30 characters and truncated if + * longer. + * + *
+ * + * The above text is largely inspired from Peter A. Darnell and + * Philip E. Margolis' highly recommended book "C -- a Software + * Engineering Approach", ISBN 0-387-97389-3. + */ + class LOG4CPLUS_EXPORT PatternLayout : public Layout { + public: + // Ctors and dtor + PatternLayout(const log4cplus::tstring& pattern); + PatternLayout(const log4cplus::helpers::Properties& properties); + virtual ~PatternLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + void init(const log4cplus::tstring& pattern, unsigned ndcMaxDepth = 0); + + // Data + log4cplus::tstring pattern; + std::vector parsedPattern; + + private: + // Disallow copying of instances of this class + PatternLayout(const PatternLayout&); + PatternLayout& operator=(const PatternLayout&); + }; + + + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_LAYOUT_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/logger.h b/libs/log4cplus/include/log4cplus/logger.h new file mode 100644 index 0000000..1423106 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/logger.h @@ -0,0 +1,344 @@ +// Module: Log4CPLUS +// File: logger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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. + +/** @file + * This header defines the Logger class and the logging macros. */ + +#ifndef _LOG4CPLUS_LOGGERHEADER_ +#define _LOG4CPLUS_LOGGERHEADER_ + +#include +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + // Forward declarations + + class Appender; + class Hierarchy; + class HierarchyLocker; + class DefaultLoggerFactory; + + namespace spi + { + + class LoggerImpl; + + } + + + /** \typedef std::vector LoggerList + * This is a list of {@link Logger Loggers}. */ + typedef std::vector LoggerList; + + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + * + * See the user manual for an + * introduction on this class. + */ + class LOG4CPLUS_EXPORT Logger + : public log4cplus::spi::AppenderAttachable + { + public: + // Static Methods + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + static bool exists(const log4cplus::tstring& name); + + /* + * Returns all the currently defined loggers in the default + * hierarchy. + * + * The root logger is not included in the returned + * list. + */ + static LoggerList getCurrentLoggers(); + + /** + * Return the default Hierarchy instance. + */ + static Hierarchy& getDefaultHierarchy(); + + /** + * Retrieve a logger with name name. If the named + * logger already exists, then the existing instance will be returned. + * Otherwise, a new instance is created. + * + * By default, loggers do not have a set LogLevel but inherit + * it from the hierarchy. This is one of the central features of + * log4cplus. + * + * @param name The name of the logger to retrieve. + */ + static Logger getInstance(const log4cplus::tstring& name); + + /** + * Like getInstance() except that the type of logger + * instantiated depends on the type returned by the {@link + * spi::LoggerFactory#makeNewLoggerInstance} method of the + * factory parameter. + * + * This method is intended to be used by sub-classes. + * + * @param name The name of the logger to retrieve. + * @param factory A {@link spi::LoggerFactory} implementation that will + * actually create a new Instance. + */ + static Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Return the root of the default logger hierrachy. + * + * The root logger is always instantiated and available. It's + * name is "root". + * + * Nevertheless, calling {@link #getInstance + * Logger.getInstance("root")} does not retrieve the root logger + * but a logger just under root named "root". + */ + static Logger getRoot(); + + /** + * Calling this method will safely close and remove all + * appenders in all the loggers including root contained in the + * default hierachy. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + static void shutdown(); + + // Non-Static Methods + /** + * If assertionVal parameter is false, then + * logs msg with FATAL_LOG_LEVEL log level. + * + * @param assertionVal Truth value of assertion condition. + * @param msg The message to print if assertion is + * false. + */ + void assertion(bool assertionVal, const log4cplus::tstring& msg) const; + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + void closeNestedAppenders() const; + + /** + * Check whether this logger is enabled for a given + * LogLevel passed as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1) const; + + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + void forcedLog(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1) const; + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event the event to log. + */ + void callAppenders(const spi::InternalLoggingEvent& event) const; + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel, can be NOT_SET_LOG_LEVEL. + */ + LogLevel getLogLevel() const; + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel ll); + + /** + * Return the the {@link Hierarchy} where this Logger instance is + * attached. + */ + Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring getName() const; + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + // AppenderAttachable Methods + virtual void addAppender(SharedAppenderPtr newAppender); + + virtual SharedAppenderPtrList getAllAppenders(); + + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + virtual void removeAllAppenders(); + + virtual void removeAppender(SharedAppenderPtr appender); + + virtual void removeAppender(const log4cplus::tstring& name); + + Logger (); + Logger(const Logger& rhs); + Logger& operator=(const Logger& rhs); + virtual ~Logger(); + + void swap (Logger &); + + /** + * Used to retrieve the parent of this Logger in the + * Logger tree. + */ + Logger getParent() const; + + protected: + // Data + /** This is a pointer to the implementation class. */ + spi::LoggerImpl * value; + + private: + // Ctors + /** + * This constructor created a new Logger instance + * with a pointer to a Logger implementation. + * + * You should not create loggers directly. + * + * @param ptr A pointer to the Logger implementation. This value + * cannot be NULL. + */ + Logger(spi::LoggerImpl * ptr); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::Hierarchy; + friend class log4cplus::HierarchyLocker; + friend class log4cplus::DefaultLoggerFactory; + }; + + + /** + * This class is used to create the default implementation of + * the Logger class + */ + class LOG4CPLUS_EXPORT DefaultLoggerFactory : public spi::LoggerFactory { + public: + Logger makeNewLoggerInstance(const log4cplus::tstring& name, Hierarchy& h); + }; + + + + /** + * This class is used to produce "Trace" logging. When an instance of + * this class is created, it will log a "ENTER: " + msg + * log message if TRACE_LOG_LEVEL is enabled for logger. + * When an instance of this class is destroyed, it will log a + * "ENTER: " + msg log message if TRACE_LOG_LEVEL is enabled + * for logger. + * + * @see LOG4CPLUS_TRACE + */ + class TraceLogger + { + public: + TraceLogger(const Logger& l, const log4cplus::tstring& _msg, + const char* _file=NULL, int _line=-1) + : logger(l), msg(_msg), file(_file), line(_line) + { if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("ENTER: ") + msg, file, line); + } + + ~TraceLogger() + { if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("EXIT: ") + msg, file, line); + } + + private: + Logger logger; + log4cplus::tstring msg; + const char* file; + int line; + }; + +} // end namespace log4cplus + + +#include + + +#endif // _LOG4CPLUS_LOGGERHEADER_ + diff --git a/libs/log4cplus/include/log4cplus/loggingmacros.h b/libs/log4cplus/include/log4cplus/loggingmacros.h new file mode 100644 index 0000000..fb95504 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/loggingmacros.h @@ -0,0 +1,191 @@ +// Module: Log4CPLUS +// File: loggingmacros.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file + * This header defines the logging macros. */ + +#ifndef _LOG4CPLUS_LOGGING_MACROS_HEADER_ +#define _LOG4CPLUS_LOGGING_MACROS_HEADER_ + +#include +#include + + +#if defined(LOG4CPLUS_DISABLE_FATAL) && !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_DISABLE_ERROR +#endif +#if defined(LOG4CPLUS_DISABLE_ERROR) && !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_DISABLE_WARN +#endif +#if defined(LOG4CPLUS_DISABLE_WARN) && !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_DISABLE_INFO +#endif +#if defined(LOG4CPLUS_DISABLE_INFO) && !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DISABLE_DEBUG +#endif +#if defined(LOG4CPLUS_DISABLE_DEBUG) && !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_DISABLE_TRACE +#endif + + +#if defined (LOG4CPLUS_SINGLE_THREADED) + +namespace log4cplus +{ + +extern LOG4CPLUS_EXPORT tostringstream _macros_oss; + +LOG4CPLUS_EXPORT void _clear_tostringstream (tostringstream &); + +} // namespace log4cplus + + +#define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel) \ + do { \ + if((logger).isEnabledFor(log4cplus::logLevel##_LOG_LEVEL)) { \ + log4cplus::_clear_tostringstream (log4cplus::_macros_oss); \ + log4cplus::_macros_oss << logEvent; \ + (logger).forcedLog(log4cplus::logLevel##_LOG_LEVEL, \ + log4cplus::_macros_oss.str(), __FILE__, __LINE__); \ + } \ + } while (0) + + +#else // defined (LOG4CPLUS_SINGLE_THREADED) + +#define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel) \ + do { \ + if((logger).isEnabledFor(log4cplus::logLevel##_LOG_LEVEL)) { \ + log4cplus::tostringstream _log4cplus_buf; \ + _log4cplus_buf << logEvent; \ + (logger).forcedLog(log4cplus::logLevel##_LOG_LEVEL, \ + _log4cplus_buf.str(), __FILE__, __LINE__); \ + } \ + } while (0) + + +#endif // defined (LOG4CPLUS_SINGLE_THREADED) + +#define LOG4CPLUS_MACRO_STR_BODY(logger, logEvent, logLevel) \ + do { \ + if((logger).isEnabledFor(log4cplus::logLevel##_LOG_LEVEL)) { \ + (logger).forcedLog(log4cplus::logLevel##_LOG_LEVEL, \ + logEvent, __FILE__, __LINE__); \ + } \ + } while(0) + + +/** + * @def LOG4CPLUS_TRACE(logger, logEvent) This macro creates a TraceLogger + * to log a TRACE_LOG_LEVEL message to logger upon entry and + * exiting of a method. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) \ + log4cplus::TraceLogger _log4cplus_trace_logger(logger, logEvent, \ + __FILE__, __LINE__); +#define LOG4CPLUS_TRACE(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, TRACE) +#define LOG4CPLUS_TRACE_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, TRACE) +#else +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) do { } while (0) +#define LOG4CPLUS_TRACE(logger, logEvent) do { } while (0) +#define LOG4CPLUS_TRACE_STR(logger, logEvent) do { } while (0) +#endif + +/** + * @def LOG4CPLUS_DEBUG(logger, logEvent) This macro is used to log a + * DEBUG_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DEBUG(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, DEBUG) +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, DEBUG) +#else +#define LOG4CPLUS_DEBUG(logger, logEvent) do { } while (0) +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) do { } while (0) +#endif + +/** + * @def LOG4CPLUS_INFO(logger, logEvent) This macro is used to log a + * INFO_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_INFO(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO) +#define LOG4CPLUS_INFO_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, INFO) +#else +#define LOG4CPLUS_INFO(logger, logEvent) do { } while (0) +#define LOG4CPLUS_INFO_STR(logger, logEvent) do { } while (0) +#endif + +/** + * @def LOG4CPLUS_WARN(logger, logEvent) This macro is used to log a + * WARN_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_WARN(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, WARN) +#define LOG4CPLUS_WARN_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, WARN) +#else +#define LOG4CPLUS_WARN(logger, logEvent) do { } while (0) +#define LOG4CPLUS_WARN_STR(logger, logEvent) do { } while (0) +#endif + +/** + * @def LOG4CPLUS_ERROR(logger, logEvent) This macro is used to log a + * ERROR_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_ERROR(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, ERROR) +#define LOG4CPLUS_ERROR_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, ERROR) +#else +#define LOG4CPLUS_ERROR(logger, logEvent) do { } while (0) +#define LOG4CPLUS_ERROR_STR(logger, logEvent) do { } while (0) +#endif + +/** + * @def LOG4CPLUS_FATAL(logger, logEvent) This macro is used to log a + * FATAL_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_FATAL) +#define LOG4CPLUS_FATAL(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, FATAL) +#define LOG4CPLUS_FATAL_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, FATAL) +#else +#define LOG4CPLUS_FATAL(logger, logEvent) do { } while (0) +#define LOG4CPLUS_FATAL_STR(logger, logEvent) do { } while (0) +#endif + +#endif /* _LOG4CPLUS_LOGGING_MACROS_HEADER_ */ + diff --git a/libs/log4cplus/include/log4cplus/loglevel.h b/libs/log4cplus/include/log4cplus/loglevel.h new file mode 100644 index 0000000..8e7dfeb --- /dev/null +++ b/libs/log4cplus/include/log4cplus/loglevel.h @@ -0,0 +1,183 @@ +// Module: Log4CPLUS +// File: loglevel.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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. + +/** @file + * This header defines the LogLevel type. + */ + +#ifndef LOG4CPLUS_LOGLEVEL_HEADER_ +#define LOG4CPLUS_LOGLEVEL_HEADER_ + +#include +#include + +#include + +namespace log4cplus { + + /** + * \typedef int LogLevel + * Defines the minimum set of priorities recognized by the system, + * that is {@link #FATAL_LOG_LEVEL}, {@link #ERROR_LOG_LEVEL}, {@link + * #WARN_LOG_LEVEL}, {@link #INFO_LOG_LEVEL}, {@link #DEBUG_LOG_LEVEL}, + * and {@link #TRACE_LOG_LEVEL}. + */ + typedef int LogLevel; + + /** \var const LogLevel OFF_LOG_LEVEL + * The OFF_LOG_LEVEL LogLevel is used during configuration to + * turn off logging. */ + const LogLevel OFF_LOG_LEVEL = 60000; + + /** \var const LogLevel FATAL_LOG_LEVEL + * The FATAL_LOG_LEVEL LogLevel designates very severe error + * events that will presumably lead the application to abort. */ + const LogLevel FATAL_LOG_LEVEL = 50000; + + /** \var const LogLevel ERROR_LOG_LEVEL + * The ERROR_LOG_LEVEL LogLevel designates error events that + * might still allow the application to continue running. */ + const LogLevel ERROR_LOG_LEVEL = 40000; + + /** \var const LogLevel WARN_LOG_LEVEL + * The WARN_LOG_LEVEL LogLevel designates potentially harmful + * situations. */ + const LogLevel WARN_LOG_LEVEL = 30000; + + /** \var const LogLevel INFO_LOG_LEVEL + * The INFO_LOG_LEVEL LogLevel designates informational + * messages that highlight the progress of the application at + * coarse-grained level. */ + const LogLevel INFO_LOG_LEVEL = 20000; + + /** \var const LogLevel DEBUG_LOG_LEVEL + * The DEBUG_LOG_LEVEL LogLevel designates fine-grained + * informational events that are most useful to debug an application. */ + const LogLevel DEBUG_LOG_LEVEL = 10000; + + /** \var const LogLevel TRACE_LOG_LEVEL + * The TRACE_LOG_LEVEL LogLevel is used to "trace" entry + * and exiting of methods. */ + const LogLevel TRACE_LOG_LEVEL = 0; + + /** \var const LogLevel ALL_LOG_LEVEL + * The ALL_LOG_LEVEL LogLevel is used during configuration to + * turn on all logging. */ + const LogLevel ALL_LOG_LEVEL = TRACE_LOG_LEVEL; + + /** \var const LogLevel NOT_SET_LOG_LEVEL + * The NOT_SET_LOG_LEVEL LogLevel is used to indicated that + * no particular LogLevel is desired and that the default should be used. + */ + const LogLevel NOT_SET_LOG_LEVEL = -1; + + + /** + * This method type defined the signature of methods that convert LogLevels + * into strings. + * + * Note: Must return an empty tstring for unrecognized values. + */ + typedef log4cplus::tstring (*LogLevelToStringMethod)(LogLevel); + + /** + * This method type defined the signature of methods that convert strings + * into LogLevels. + * + * Note: Must return NOT_SET_LOG_LEVEL for unrecognized values. + */ + typedef LogLevel (*StringToLogLevelMethod)(const log4cplus::tstring&); + + + + /** + * This class is used to "manage" LogLevel definitions. This class is also + * how "derived" LogLevels are created. Here are the steps to creating a + * "derived" LogLevel: + *
    + *
  1. Create a LogLevel constant (greater than 0)
  2. + *
  3. Define a string to represent that constant
  4. + *
  5. Implement a LogLevelToStringMethod method.
  6. + *
  7. Implement a StringToLogLevelMethod method.
  8. + *
  9. create a "static initializer" that registers those 2 methods + * with the LogLevelManager singleton.
  10. + *
+ */ + class LOG4CPLUS_EXPORT LogLevelManager { + public: + LogLevelManager(); + ~LogLevelManager(); + + /** + * This method is called by all Layout classes to convert a LogLevel + * into a string. + * + * Note: It traverses the list of LogLevelToStringMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + log4cplus::tstring toString(LogLevel ll) const; + + /** + * This method is called by all classes internally to log4cplus to + * convert a string into a LogLevel. + * + * Note: It traverses the list of StringToLogLevelMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + LogLevel fromString(const log4cplus::tstring& s) const; + + /** + * When creating a "derived" LogLevel, a LogLevelToStringMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushFromStringMethod + */ + void pushToStringMethod(LogLevelToStringMethod newToString); + + /** + * When creating a "derived" LogLevel, a StringToLogLevelMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushToStringMethod + */ + void pushFromStringMethod(StringToLogLevelMethod newFromString); + + private: + // Data + void* toStringMethods; + void* fromStringMethods; + + // Disable Copy + LogLevelManager(const LogLevelManager&); + LogLevelManager& operator=(const LogLevelManager&); + }; + + /** + * Returns the singleton LogLevelManager. + */ + LOG4CPLUS_EXPORT LogLevelManager& getLogLevelManager(); + +} + + +#endif // LOG4CPLUS_LOGLEVEL_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/ndc.h b/libs/log4cplus/include/log4cplus/ndc.h new file mode 100644 index 0000000..6498816 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/ndc.h @@ -0,0 +1,318 @@ +// Module: Log4CPLUS +// File: ndc.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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. + +/** @file + * This header defined the NDC class. + */ + +#ifndef _LO4CPLUS_NDC_HEADER_ +#define _LO4CPLUS_NDC_HEADER_ + +#include +#include +#include + +#include +#include + +#if (defined(__MWERKS__) && defined(__MACOS__)) +using std::size_t; +#endif + + +namespace log4cplus { + // Forward declarations + class NDC; + struct DiagnosticContext; + typedef std::stack DiagnosticContextStack; + +#if defined (_MSC_VER) || defined (__HP_aCC) + LOG4CPLUS_EXPORT NDC& getNDC(); +#endif + + + /** + * The NDC class implements nested diagnostic contexts as + * defined by Neil Harrison in the article "Patterns for Logging + * Diagnostic Messages" part of the book "Pattern Languages of + * Program Design 3" edited by Martin et al. + * + * A Nested Diagnostic Context, or NDC in short, is an instrument + * to distinguish interleaved log output from different sources. Log + * output is typically interleaved when a server handles multiple + * clients near-simultaneously. + * + * Interleaved log output can still be meaningful if each log entry + * from different contexts had a distinctive stamp. This is where NDCs + * come into play. + * + * Note that NDCs are managed on a per thread + * basis. NDC operations such as {@link #push}, {@link + * #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth} + * affect the NDC of the current thread only. NDCs of other + * threads remain unaffected. + * + * For example, a server can build a per client request NDC + * consisting the clients host name and other information contained in + * the the request. Cookies are another source of distinctive + * information. To build an NDC one uses the {@link #push} + * operation. Simply put, + * + *
    + *
  • Contexts can be nested. + * + *
  • When entering a context, call getNDC().push(). As a + * side effect, if there is no nested diagnostic context for the + * current thread, this method will create it. + * + *
  • When leaving a context, call getNDC().pop(). + * + *
  • When exiting a thread make sure to call {@link #remove + * NDC.remove()}. + *
+ * + * There is no penalty for forgetting to match each + * push operation with a corresponding pop, + * except the obvious mismatch between the real application context + * and the context set in the NDC. Use of the {@link NDCContextCreator} + * class can automate this process and make your code exception-safe. + * + * If configured to do so, {@link log4cplus::PatternLayout} and {@link + * log4cplus::TTCCLayout} instances automatically retrieve the nested diagnostic + * context for the current thread without any user intervention. + * Hence, even if a server is serving multiple clients + * simultaneously, the logs emanating from the same code (belonging to + * the same logger) can still be distinguished because each client + * request will have a different NDC tag. + * + * Heavy duty systems should call the {@link #remove} method when + * leaving the run method of a thread. This ensures that the memory + * used by the thread can be freed. + * + * A thread may inherit the nested diagnostic context of another + * (possibly parent) thread using the {@link #inherit inherit} + * method. A thread may obtain a copy of its NDC with the {@link + * #cloneStack cloneStack} method and pass the reference to any other + * thread, in particular to a child. + */ + class LOG4CPLUS_EXPORT NDC : protected log4cplus::helpers::LogLogUser { + public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + * + * This method is equivalent to calling the {@link #setMaxDepth} + * method with a zero maxDepth argument. + */ + void clear(); + + /** + * Clone the diagnostic context for the current thread. + * + * Internally a diagnostic context is represented as a stack. A + * given thread can supply the stack (i.e. diagnostic context) to a + * child thread so that the child can inherit the parent thread's + * diagnostic context. + * + * The child thread uses the {@link #inherit inherit} method to + * inherit the parent's diagnostic context. + * + * @return Stack A clone of the current thread's diagnostic context. + */ + DiagnosticContextStack cloneStack(); + + /** + * Inherit the diagnostic context of another thread. + * + * The parent thread can obtain a reference to its diagnostic + * context using the {@link #cloneStack} method. It should + * communicate this information to its child so that it may inherit + * the parent's diagnostic context. + * + * The parent's diagnostic context is cloned before being + * inherited. In other words, once inherited, the two diagnostic + * contexts can be managed independently. + * + * @param stack The diagnostic context of the parent thread. + */ + void inherit(const DiagnosticContextStack& stack); + + /** + * Used when printing the diagnostic context. + */ + log4cplus::tstring get(); + + /** + * Get the current nesting depth of this diagnostic context. + * + * @see #setMaxDepth + */ + size_t getDepth(); + + /** + * Clients should call this method before leaving a diagnostic + * context. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is + * returned. If each call to push() is paired with a call to + * pop() (even in presence of thrown exceptions), the last + * pop() call frees the memory used by NDC for this + * thread. Otherwise, remove() must be called at the end of + * the thread to free the memory used by NDC for the thread. + * + * @return String The innermost diagnostic context. + * + * @see NDCContextCreator, remove(), push() + */ + log4cplus::tstring pop(); + + /** + * Looks at the last diagnostic context at the top of this NDC + * without removing it. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is returned. + * + * @return String The innermost diagnostic context. + */ + log4cplus::tstring peek(); + + /** + * Push new diagnostic context information for the current thread. + * + * The contents of the message parameter is + * determined solely by the client. Each call to push() should + * be paired with a call to pop(). + * + * @param message The new diagnostic context information. + * + * @see NDCContextCreator, pop(), remove() + */ + void push(const log4cplus::tstring& message); + + /** + * Remove the diagnostic context for this thread. + * + * Each thread that created a diagnostic context by calling + * push() should call this method before exiting. Otherwise, + * the memory used by the thread cannot be reclaimed. It is + * possible to omit this call if and only if each push() call + * is always paired with a pop() call (even in presence of + * thrown exceptions). Then the memory used by NDC will be + * returned by the last pop() call and a call to remove() will + * be no-op. + */ + void remove(); + + /** + * Set maximum depth of this diagnostic context. If the current + * depth is smaller or equal to maxDepth, then no + * action is taken. + * + * This method is a convenient alternative to multiple {@link + * #pop} calls. Moreover, it is often the case that at the end of + * complex call sequences, the depth of the NDC is + * unpredictable. The setMaxDepth method circumvents + * this problem. + * + * For example, the combination + *
+         *    void foo() {
+         *       size_t depth = NDC.getDepth();
+         *
+         *       ... complex sequence of calls
+         *
+         *       NDC.setMaxDepth(depth);
+         *    }
+         * 
+ * + * ensures that between the entry and exit of foo the depth of the + * diagnostic stack is conserved. + * + * Note: Use of the {@link NDCContextCreator} class will solve + * this particular problem. + * + * @see #getDepth + */ + void setMaxDepth(size_t maxDepth); + + // Dtor + ~NDC(); + + private: + // Methods + DiagnosticContextStack* getPtr(); + + // Data + LOG4CPLUS_THREAD_LOCAL_TYPE threadLocal; + + // Disallow construction (and copying) except by getNDC() + NDC(); + NDC(const NDC&); + NDC& operator=(const NDC&); + + // Friends +#if defined (_MSC_VER) || defined (__HP_aCC) + friend LOG4CPLUS_EXPORT NDC& getNDC(); +#else + friend NDC& getNDC(); +#endif + }; + + + /** + * Return a reference to the singleton object. + */ + LOG4CPLUS_EXPORT NDC& getNDC(); + + + /** + * This is the internal object that is stored on the NDC stack. + */ + struct LOG4CPLUS_EXPORT DiagnosticContext { + // Ctors + DiagnosticContext(const log4cplus::tstring& message, DiagnosticContext *parent); + DiagnosticContext(const log4cplus::tstring& message); + + // Data + log4cplus::tstring message; /*!< The message at this context level. */ + log4cplus::tstring fullMessage; /*!< The entire message stack. */ + }; + + + /** + * This class ensures that a {@link NDC#push} call is always matched with + * a {@link NDC#pop} call even in the face of exceptions. + */ + class LOG4CPLUS_EXPORT NDCContextCreator { + public: + /** Pushes msg onto the NDC stack. */ + NDCContextCreator(const log4cplus::tstring& msg); + + /** Pops the NDC stack. */ + ~NDCContextCreator(); + }; + +} // end namespace log4cplus + + +#endif // _LO4CPLUS_NDC_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/nteventlogappender.h b/libs/log4cplus/include/log4cplus/nteventlogappender.h new file mode 100644 index 0000000..58da44c --- /dev/null +++ b/libs/log4cplus/include/log4cplus/nteventlogappender.h @@ -0,0 +1,81 @@ +// Module: Log4CPLUS +// File: nteventlogappender.h +// Created: 4/2003 +// Author: Michael CATANZARITI +// +// Copyright 2003-2009 Michael CATANZARITI +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ +#define _LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ + +#include +#include + +#if defined(_WIN32) +# if ! defined (LOG4CPLUS_HAVE_NT_EVENT_LOG) +# error "Your platform does not support NT event log." +# else + + +namespace log4cplus { + + /** + * Appends log events to NT EventLog. + */ + class LOG4CPLUS_EXPORT NTEventLogAppender : public Appender { + public: + // ctors + NTEventLogAppender(const log4cplus::tstring& server, + const log4cplus::tstring& log, + const log4cplus::tstring& source); + NTEventLogAppender(const log4cplus::helpers::Properties properties); + + // dtor + virtual ~NTEventLogAppender(); + + // public Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + virtual WORD getEventType(const spi::InternalLoggingEvent& event); + virtual WORD getEventCategory(const spi::InternalLoggingEvent& event); + void init(); + + /* + * Add this source with appropriate configuration keys to the registry. + */ + void addRegistryInfo(); + + // Data + log4cplus::tstring server; + log4cplus::tstring log; + log4cplus::tstring source; + HANDLE hEventLog; + SID* pCurrentUserSID; + + private: + // Disallow copying of instances of this class + NTEventLogAppender(const NTEventLogAppender&); + NTEventLogAppender& operator=(const NTEventLogAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_NT_EVENT_LOG +#endif // _WIN32 +#endif //_LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/nullappender.h b/libs/log4cplus/include/log4cplus/nullappender.h new file mode 100644 index 0000000..32063f2 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/nullappender.h @@ -0,0 +1,60 @@ +// Module: Log4CPLUS +// File: nullappender.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_NULL_APPENDER_HEADER_ +#define _LOG4CPLUS_NULL_APPENDER_HEADER_ + +#include +#include +#include + + +namespace log4cplus { + + /** + * Appends log events to a file. + */ + class LOG4CPLUS_EXPORT NullAppender : public Appender { + public: + // Ctors + NullAppender(); + NullAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~NullAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + NullAppender(const NullAppender&); + NullAppender& operator=(const NullAppender&); + }; + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_NULL_APPENDER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/socketappender.h b/libs/log4cplus/include/log4cplus/socketappender.h new file mode 100644 index 0000000..5b14158 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/socketappender.h @@ -0,0 +1,161 @@ +// Module: LOG4CPLUS +// File: socketappender.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SOCKET_APPENDER_HEADER_ +#define _LOG4CPLUS_SOCKET_APPENDER_HEADER_ + +#include +#include +#include +#include + + +#ifndef UNICODE +# define LOG4CPLUS_MAX_MESSAGE_SIZE (8*1024) +#else +# define LOG4CPLUS_MAX_MESSAGE_SIZE (2*8*1024) +#endif + + +namespace log4cplus { + + /** + * Sends {@link spi::InternalLoggingEvent} objects to a remote a log server. + * + * The SocketAppender has the following properties: + * + *
    + * + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client. + * + *
  • SocketAppenders do not use a layout. + * + *
  • Remote logging uses the TCP protocol. Consequently, if + * the server is reachable, then log events will eventually arrive + * at the server. + * + *
  • If the remote server is down, the logging requests are + * simply dropped. However, if and when the server comes back up, + * then event transmission is resumed transparently. This + * transparent reconneciton is performed by a connector + * thread which periodically attempts to connect to the server. + * + *
  • Logging events are automatically buffered by the + * native TCP implementation. This means that if the link to server + * is slow but still faster than the rate of (log) event production + * by the client, the client will not be affected by the slow + * network connection. However, if the network connection is slower + * then the rate of event production, then the client can only + * progress at the network rate. In particular, if the network link + * to the the server is down, the client will be blocked. + * + *
  • On the other hand, if the network link is up, but the server + * is down, the client will not be blocked when making log requests + * but the log events will be lost due to server unavailability. + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to.
+ * + *
ServerName
+ *
Host name of event's origin prepended to each event.
+ * + *
+ */ + class LOG4CPLUS_EXPORT SocketAppender : public Appender { + public: + // Ctors + SocketAppender(const log4cplus::tstring& host, int port, + const log4cplus::tstring& serverName = tstring()); + SocketAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~SocketAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + void initConnector (); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + int port; + log4cplus::tstring serverName; + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + class LOG4CPLUS_EXPORT ConnectorThread; + friend class ConnectorThread; + + class LOG4CPLUS_EXPORT ConnectorThread + : public thread::AbstractThread + , public helpers::LogLogUser + { + public: + ConnectorThread (SocketAppender &); + virtual ~ConnectorThread (); + + virtual void run(); + + void terminate (); + void trigger (); + + protected: + SocketAppender & sa; + thread::ManualResetEvent trigger_ev; + bool exit_flag; + }; + + volatile bool connected; + helpers::SharedObjectPtr connector; +#endif + + private: + // Disallow copying of instances of this class + SocketAppender(const SocketAppender&); + SocketAppender& operator=(const SocketAppender&); + }; + + namespace helpers { + LOG4CPLUS_EXPORT + SocketBuffer convertToBuffer(const log4cplus::spi::InternalLoggingEvent& event, + const log4cplus::tstring& serverName); + + LOG4CPLUS_EXPORT + log4cplus::spi::InternalLoggingEvent readFromBuffer(SocketBuffer& buffer); + } // end namespace helpers + +} // end namespace log4cplus + +#endif // _LOG4CPLUS_SOCKET_APPENDER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/spi/appenderattachable.h b/libs/log4cplus/include/log4cplus/spi/appenderattachable.h new file mode 100644 index 0000000..b486e5f --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/appenderattachable.h @@ -0,0 +1,84 @@ +// Module: Log4CPLUS +// File: appenderattachable.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ +#define _LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + +#include +#include +#include +#include +#include + +namespace log4cplus { + // Forward Declarations + typedef helpers::SharedObjectPtr SharedAppenderPtr; + typedef std::vector SharedAppenderPtrList; + + namespace spi { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachable { + public: + // Methods + /** + * Add an appender. + */ + virtual void addAppender(SharedAppenderPtr newAppender) = 0; + + /** + * Get all previously added appenders as an Enumeration. + */ + virtual SharedAppenderPtrList getAllAppenders() = 0; + + /** + * Get an appender by name. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name) = 0; + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders() = 0; + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender) = 0; + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name) = 0; + + // Dtor + virtual ~AppenderAttachable() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // _LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/spi/factory.h b/libs/log4cplus/include/log4cplus/spi/factory.h new file mode 100644 index 0000000..7ed0be0 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/factory.h @@ -0,0 +1,185 @@ +// Module: Log4CPLUS +// File: factory.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2010 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_FACTORY_HEADER_ +#define LOG4CPLUS_SPI_FACTORY_HEADER_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class for all factories. + */ + class LOG4CPLUS_EXPORT BaseFactory { + public: + virtual ~BaseFactory() = 0; + + /** + * Returns the typename of the objects this factory creates. + */ + virtual log4cplus::tstring getTypeName() = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT AppenderFactory : public BaseFactory { + public: + typedef Appender ProductType; + typedef SharedAppenderPtr ProductPtr; + + AppenderFactory(); + virtual ~AppenderFactory() = 0; + + /** + * Create an "Appender" object. + */ + virtual SharedAppenderPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Layout" + * objects. + */ + class LOG4CPLUS_EXPORT LayoutFactory : public BaseFactory { + public: + typedef Layout ProductType; + typedef std::auto_ptr ProductPtr; + + LayoutFactory(); + virtual ~LayoutFactory() = 0; + + /** + * Create a "Layout" object. + */ + virtual std::auto_ptr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT FilterFactory : public BaseFactory { + public: + typedef Filter ProductType; + typedef FilterPtr ProductPtr; + + FilterFactory(); + virtual ~FilterFactory() = 0; + + /** + * Create a "Filter" object. + */ + virtual FilterPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This template class is used as a "Factory Registry". Objects are + * "entered" into the registry with a "name" using the + * put() method. (The registry then owns the object.) + * These object can then be retrieved using the get() + * method. + * + * Note: This class is Thread-safe. + */ + template + class LOG4CPLUS_EXPORT FactoryRegistry : ObjectRegistryBase { + public: + typedef T product_type; + + virtual ~FactoryRegistry() { + clear(); + } + + // public methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool put(std::auto_ptr object) { + bool putValResult = putVal(object->getTypeName(), object.get()); + object.release(); + return putValResult; + } + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + T* get(const log4cplus::tstring& name) const { + return static_cast(getVal(name)); + } + + protected: + virtual void deleteObject(void *object) const { + delete static_cast(object); + } + }; + + + typedef FactoryRegistry AppenderFactoryRegistry; + typedef FactoryRegistry LayoutFactoryRegistry; + typedef FactoryRegistry FilterFactoryRegistry; + + + /** + * Returns the "singleton" AppenderFactoryRegistry. + */ + LOG4CPLUS_EXPORT AppenderFactoryRegistry& getAppenderFactoryRegistry(); + + /** + * Returns the "singleton" LayoutFactoryRegistry. + */ + LOG4CPLUS_EXPORT LayoutFactoryRegistry& getLayoutFactoryRegistry(); + + /** + * Returns the "singleton" FilterFactoryRegistry. + */ + LOG4CPLUS_EXPORT FilterFactoryRegistry& getFilterFactoryRegistry(); + + } +} + + +#endif // LOG4CPLUS_SPI_FACTORY_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/spi/filter.h b/libs/log4cplus/include/log4cplus/spi/filter.h new file mode 100644 index 0000000..ef8b573 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/filter.h @@ -0,0 +1,273 @@ +// Module: Log4CPLUS +// File: filter.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 1999-2010 Tad E. Smith +// +// 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. + +/** @file + * This header defines Filter and all of it's subclasses. */ + +#ifndef LOG4CPLUS_SPI_FILTER_HEADER_ +#define LOG4CPLUS_SPI_FILTER_HEADER_ + +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + + enum FilterResult { DENY, /**< The log event must be dropped immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + NEUTRAL, /**< This filter is neutral with respect to + * the log event; the remaining filters, if + * if any, should be consulted for a final + * decision. */ + ACCEPT /**< The log event must be logged immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + }; + + // Forward Declarations + class Filter; + + + /** + * This method is used to filter an InternalLoggingEvent. + * + * Note: filter can be NULL. + */ + LOG4CPLUS_EXPORT FilterResult checkFilter(const Filter* filter, + const InternalLoggingEvent& event); + + typedef helpers::SharedObjectPtr FilterPtr; + + + /** + * Users should extend this class to implement customized logging + * event filtering. Note that the {@link Logger} and {@link + * Appender} classes have built-in filtering rules. It is suggested + * that you first use and understand the built-in rules before rushing + * to write your own custom filters. + * + * This abstract class assumes and also imposes that filters be + * organized in a linear chain. The {@link #decide + * decide(LoggingEvent)} method of each filter is called sequentially, + * in the order of their addition to the chain. + * + * If the value {@link #DENY} is returned, then the log event is + * dropped immediately without consulting with the remaining + * filters. + * + * If the value {@link #NEUTRAL} is returned, then the next filter + * in the chain is consulted. If there are no more filters in the + * chain, then the log event is logged. Thus, in the presence of no + * filters, the default behaviour is to log all logging events. + * + * If the value {@link #ACCEPT} is returned, then the log + * event is logged without consulting the remaining filters. + * + * The philosophy of log4cplus filters is largely inspired from the + * Linux ipchains. + */ + class LOG4CPLUS_EXPORT Filter + : public virtual log4cplus::helpers::SharedObject + { + public: + // ctor and dtor + Filter(); + virtual ~Filter(); + + // Methods + /** + * Appends filter to the end of this filter chain. + */ + void appendFilter(FilterPtr filter); + + /** + * If the decision is DENY, then the event will be + * dropped. If the decision is NEUTRAL, then the next + * filter, if any, will be invoked. If the decision is ACCEPT then + * the event will be logged without consulting with other filters in + * the chain. + * + * @param event The LoggingEvent to decide upon. + * @return The decision of the filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const = 0; + + // Data + /** + * Points to the next filter in the filter chain. + */ + FilterPtr next; + }; + + + + /** + * This filter drops all logging events. + * + * You can add this filter to the end of a filter chain to + * switch from the default "accept all unless instructed otherwise" + * filtering behaviour to a "deny all unless instructed otherwise" + * behaviour. + */ + class LOG4CPLUS_EXPORT DenyAllFilter : public Filter { + public: + DenyAllFilter (); + DenyAllFilter (const log4cplus::helpers::Properties&); + + /** + * Always returns the {@link #DENY} regardless of the + * {@link InternalLoggingEvent} parameter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + }; + + + /** + * This is a very simple filter based on LogLevel matching. + * + * The filter admits two options LogLevelToMatch and + * AcceptOnMatch. If there is an exact match between the value + * of the LogLevelToMatch option and the LogLevel of the {@link + * spi::InternalLoggingEvent}, then the {@link #decide} method returns + * {@link #ACCEPT} in case the AcceptOnMatch option value is set + * to true, if it is false then {@link #DENY} + * is returned. If there is no match, {@link #NEUTRAL} is returned. + */ + class LOG4CPLUS_EXPORT LogLevelMatchFilter : public Filter { + public: + LogLevelMatchFilter(); + LogLevelMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + * + * Returns {@link #NEUTRAL} if the LogLevelToMatch + * option is not set or if there is no match. Otherwise, if + * there is a match, then the returned decision is {@link #ACCEPT} + * if the AcceptOnMatch property is set to true. + * The returned decision is {@link #DENY} if the AcceptOnMatch + * property is set to false. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelToMatch; + }; + + + + /** + * This is a very simple filter based on LogLevel matching, which can be + * used to reject messages with LogLevels outside a certain range. + * + * The filter admits three options LogLevelMin, LogLevelMax + * and AcceptOnMatch. + * + * If the LogLevel of the Logging event is not between Min and Max + * (inclusive), then {@link #DENY} is returned. + * + * If the Logging event LogLevel is within the specified range, then if + * AcceptOnMatch is true, {@link #ACCEPT} is returned, and if + * AcceptOnMatch is false, {@link #NEUTRAL} is returned. + * + * If LogLevelMin is not defined, then there is no + * minimum acceptable LogLevel (ie a LogLevel is never rejected for + * being too "low"/unimportant). If LogLevelMax is not + * defined, then there is no maximum acceptable LogLevel (ie a + * LogLevel is never rejected for beeing too "high"/important). + * + * Refer to the {@link + * Appender#setThreshold setThreshold} method + * available to all appenders for a more convenient way to + * filter out events by LogLevel. + */ + class LOG4CPLUS_EXPORT LogLevelRangeFilter : public Filter { + public: + // ctors + LogLevelRangeFilter(); + LogLevelRangeFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelMin; + LogLevel logLevelMax; + }; + + + + /** + * This is a very simple filter based on string matching. + * + * The filter admits two options StringToMatch and + * AcceptOnMatch. If there is a match between the value of the + * StringToMatch option and the message of the Logging event, + * then the {@link #decide} method returns {@link #ACCEPT} if + * the AcceptOnMatch option value is true, if it is false then + * {@link #DENY} is returned. If there is no match, {@link #NEUTRAL} + * is returned. + */ + class LOG4CPLUS_EXPORT StringMatchFilter : public Filter { + public: + // ctors + StringMatchFilter(); + StringMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Returns {@link #NEUTRAL} is there is no string match. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + log4cplus::tstring stringToMatch; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif /* LOG4CPLUS_SPI_FILTER_HEADER_ */ + + diff --git a/libs/log4cplus/include/log4cplus/spi/loggerfactory.h b/libs/log4cplus/include/log4cplus/spi/loggerfactory.h new file mode 100644 index 0000000..c353294 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/loggerfactory.h @@ -0,0 +1,55 @@ +// Module: Log4CPLUS +// File: loggerfactory.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER +#define _LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + +#include +#include +#include + + +namespace log4cplus { + // Forward Declarations + class Logger; + class Hierarchy; + + namespace spi { + /** + * Implement this interface to create new instances of Logger or + * a sub-class of Logger. + */ + class LOG4CPLUS_EXPORT LoggerFactory { + public: + /** + * Creates a new Logger object. + */ + virtual Logger makeNewLoggerInstance(const log4cplus::tstring& name, + Hierarchy& h) = 0; + virtual ~LoggerFactory() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // _LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + diff --git a/libs/log4cplus/include/log4cplus/spi/loggerimpl.h b/libs/log4cplus/include/log4cplus/spi/loggerimpl.h new file mode 100644 index 0000000..ae89673 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/loggerimpl.h @@ -0,0 +1,209 @@ +// Module: Log4CPLUS +// File: loggerimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SPI_LOGGER_HEADER_ +#define _LOG4CPLUS_SPI_LOGGER_HEADER_ + +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + class DefaultLoggerFactory; + + namespace spi { + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + * + * See the user manual for an + * introduction on this class. + */ + class LOG4CPLUS_EXPORT LoggerImpl + : public virtual log4cplus::helpers::SharedObject, + public log4cplus::helpers::AppenderAttachableImpl + { + public: + typedef helpers::SharedObjectPtr SharedLoggerImplPtr; + + // Methods + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event The event to log. + */ + virtual void callAppenders(const InternalLoggingEvent& event); + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + virtual void closeNestedAppenders(); + + /** + * Check whether this logger is enabled for a given LogLevel passed + * as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + virtual bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + virtual void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1); + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel. + */ + LogLevel getLogLevel() const { return this->ll; } + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel _ll) { this->ll = _ll; } + + /** + * Return the the {@link Hierarchy} where this Logger + * instance is attached. + */ + virtual Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring getName() const { return name; } + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + virtual ~LoggerImpl(); + + protected: + // Ctors + /** + * This constructor created a new Logger instance and + * sets its name. + * + * It is intended to be used by sub-classes only. You should not + * create loggers directly. + * + * @param name The name of the logger. + * @param h Hierarchy + */ + LoggerImpl(const log4cplus::tstring& name, Hierarchy& h); + + + // Methods + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + virtual void forcedLog(LogLevel ll, + const log4cplus::tstring& message, + const char* file=NULL, + int line=-1); + + + // Data + /** The name of this logger */ + log4cplus::tstring name; + + /** + * The assigned LogLevel of this logger. + */ + LogLevel ll; + + /** + * The parent of this logger. All loggers have at least one + * ancestor which is the root logger. + */ + SharedLoggerImplPtr parent; + + /** + * Additivity is set to true by default, that is children inherit + * the appenders of their ancestors by default. If this variable is + * set to false then the appenders found in the + * ancestors of this logger are not used. However, the children + * of this logger will inherit its appenders, unless the children + * have their additivity flag set to false too. See + * the user manual for more details. + */ + bool additive; + + private: + // Data + /** Loggers need to know what Hierarchy they are in. */ + Hierarchy& hierarchy; + + // Disallow copying of instances of this class + LoggerImpl(const LoggerImpl&); + LoggerImpl& operator=(const LoggerImpl&); + + // Friends + friend class log4cplus::Logger; + friend class log4cplus::DefaultLoggerFactory; + friend class log4cplus::Hierarchy; + }; + + typedef LoggerImpl::SharedLoggerImplPtr SharedLoggerImplPtr; + + } // end namespace spi +} // end namespace log4cplus + +#endif // _LOG4CPLUS_SPI_LOGGER_HEADER_ + + diff --git a/libs/log4cplus/include/log4cplus/spi/loggingevent.h b/libs/log4cplus/include/log4cplus/spi/loggingevent.h new file mode 100644 index 0000000..5650baf --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/loggingevent.h @@ -0,0 +1,198 @@ +// Module: Log4CPLUS +// File: loggingevent.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ +#define _LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ + +#include +#include +#include +#include +#include +#include + +namespace log4cplus { + namespace spi { + /** + * The internal representation of logging events. When an affirmative + * decision is made to log then a InternalLoggingEvent + * instance is created. This instance is passed around to the + * different log4cplus components. + * + * This class is of concern to those wishing to extend log4cplus. + */ + class LOG4CPLUS_EXPORT InternalLoggingEvent { + public: + // Ctors + /** + * Instantiate a LoggingEvent from the supplied parameters. + * + * @param logger The logger of this event. + * @param ll_ The LogLevel of this event. + * @param message_ The message of this event. + * @param filename Name of file where this event has occurred, + * can be NULL. + * @param line_ Line number in file specified by + * the filename parameter. + */ + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel ll_, + const log4cplus::tstring& message_, + const char* filename, + int line_) + : message(message_), + loggerName(logger), + ll(ll_), + ndc(), + thread(), + timestamp(log4cplus::helpers::Time::gettimeofday()), + file( ( filename + ? LOG4CPLUS_C_STR_TO_TSTRING(filename) + : log4cplus::tstring()) ), + line(line_), + threadCached(false), + ndcCached(false) + { + } + + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel ll_, + const log4cplus::tstring& ndc_, + const log4cplus::tstring& message_, + const log4cplus::tstring& thread_, + log4cplus::helpers::Time time, + const log4cplus::tstring& file_, + int line_) + : message(message_), + loggerName(logger), + ll(ll_), + ndc(ndc_), + thread(thread_), + timestamp(time), + file(file_), + line(line_), + threadCached(true), + ndcCached(true) + { + } + + InternalLoggingEvent(const log4cplus::spi::InternalLoggingEvent& rhs) + : message(rhs.getMessage()), + loggerName(rhs.getLoggerName()), + ll(rhs.getLogLevel()), + ndc(rhs.getNDC()), + thread(rhs.getThread()), + timestamp(rhs.getTimestamp()), + file(rhs.getFile()), + line(rhs.getLine()), + threadCached(true), + ndcCached(true) + { + } + + virtual ~InternalLoggingEvent(); + + + // public virtual methods + /** The application supplied message of logging event. */ + virtual const log4cplus::tstring& getMessage() const; + + /** Returns the 'type' of InternalLoggingEvent. Derived classes + * should override this method. (NOTE: Values <= 1000 are + * reserved for log4cplus and should not be used.) + */ + virtual unsigned int getType() const; + + /** Returns a copy of this object. Derived classes + * should override this method. + */ + virtual std::auto_ptr clone() const; + + + + // public methods + /** The logger of the logging event. It is set by + * the LoggingEvent constructor. + */ + const log4cplus::tstring& getLoggerName() const { return loggerName; } + + /** LogLevel of logging event. */ + LogLevel getLogLevel() const { return ll; } + + /** The nested diagnostic context (NDC) of logging event. */ + const log4cplus::tstring& getNDC() const { + if(!ndcCached) { + ndc = log4cplus::getNDC().get(); + ndcCached = true; + } + return ndc; + } + + /** The name of thread in which this logging event was generated. */ + const log4cplus::tstring& getThread() const { + if(!threadCached) { + thread = LOG4CPLUS_GET_CURRENT_THREAD_NAME; + threadCached = true; + } + return thread; + } + + /** The number of milliseconds elapsed from 1/1/1970 until logging event + * was created. */ + const log4cplus::helpers::Time& getTimestamp() const { return timestamp; } + + /** The is the file where this log statement was written */ + const log4cplus::tstring& getFile() const { return file; } + + /** The is the line where this log statement was written */ + int getLine() const { return line; } + + // public operators + log4cplus::spi::InternalLoggingEvent& + operator=(const log4cplus::spi::InternalLoggingEvent& rhs); + + // static methods + static unsigned int getDefaultType(); + + protected: + // Data + log4cplus::tstring message; + + private: + log4cplus::tstring loggerName; + LogLevel ll; + mutable log4cplus::tstring ndc; + mutable log4cplus::tstring thread; + log4cplus::helpers::Time timestamp; + log4cplus::tstring file; + int line; + /** Indicates whether or not the Threadname has been retrieved. */ + mutable bool threadCached; + /** Indicates whether or not the NDC has been retrieved. */ + mutable bool ndcCached; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // _LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/spi/objectregistry.h b/libs/log4cplus/include/log4cplus/spi/objectregistry.h new file mode 100644 index 0000000..cb10931 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/objectregistry.h @@ -0,0 +1,96 @@ +// Module: Log4CPLUS +// File: objectregistry.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ +#define LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class used to implement the functionality required + * by the ObjectRegistry template class. + */ + class LOG4CPLUS_EXPORT ObjectRegistryBase { + public: + // public methods + /** + * Tests to see whether or not an object is bound in the + * registry as name. + */ + bool exists(const log4cplus::tstring& name) const; + + /** + * Returns the names of all registered objects. + */ + std::vector getAllNames() const; + + protected: + // Ctor and Dtor + ObjectRegistryBase(); + virtual ~ObjectRegistryBase(); + + // protected methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool putVal(const log4cplus::tstring& name, void* object); + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + void* getVal(const log4cplus::tstring& name) const; + + /** + * Deletes object. + */ + virtual void deleteObject(void *object) const = 0; + + /** + * Deletes all objects from this registry. + */ + virtual void clear(); + + // Types + typedef std::map ObjectMap; + + // Data + LOG4CPLUS_MUTEX_PTR_DECLARE mutex; + ObjectMap data; + }; + + } +} + + +#endif // LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/spi/rootlogger.h b/libs/log4cplus/include/log4cplus/spi/rootlogger.h new file mode 100644 index 0000000..098abd2 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/spi/rootlogger.h @@ -0,0 +1,70 @@ +// Module: Log4CPLUS +// File: rootlogger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ +#define _LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + +#include +#include +#include + +namespace log4cplus { + namespace spi { + + /** + * RootLogger sits at the top of the logger hierachy. It is a + * regular logger except that it provides several guarantees. + * + * First, it cannot be assigned a NOT_SET_LOG_LEVEL + * LogLevel. Second, since root logger cannot have a parent, the + * getChainedLogLevel method always returns the value of the + * ll field without walking the hierarchy. + */ + class LOG4CPLUS_EXPORT RootLogger : public LoggerImpl { + public: + // Ctors + /** + * The root logger names itself as "root". However, the root + * logger cannot be retrieved by name. + */ + RootLogger(Hierarchy& h, LogLevel ll); + + // Methods + /** + * Return the assigned LogLevel value without walking the logger + * hierarchy. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Setting a NOT_SET_LOG_LEVEL value to the LogLevel of the root logger + * may have catastrophic results. We prevent this here. + */ + void setLogLevel(LogLevel ll); + + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // _LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/streams.h b/libs/log4cplus/include/log4cplus/streams.h new file mode 100644 index 0000000..1205137 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/streams.h @@ -0,0 +1,55 @@ +// Module: Log4CPLUS +// File: streams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_STREAMS_HEADER_ +#define LOG4CPLUS_STREAMS_HEADER_ + +#include +#include + +#include +#include +#define LOG4CPLUS_STREAM_NAMESPACE std + +#ifdef UNICODE + namespace log4cplus { + typedef LOG4CPLUS_STREAM_NAMESPACE::wostream tostream; + typedef LOG4CPLUS_STREAM_NAMESPACE::wistream tistream; + typedef LOG4CPLUS_STREAM_NAMESPACE::wostringstream tostringstream; + static tostream &tcout = LOG4CPLUS_STREAM_NAMESPACE::wcout; + static tostream &tcerr = LOG4CPLUS_STREAM_NAMESPACE::wcerr; + } + +LOG4CPLUS_EXPORT log4cplus::tostream& operator <<(log4cplus::tostream&, const char* psz ); + +#else + namespace log4cplus { + typedef LOG4CPLUS_STREAM_NAMESPACE::ostream tostream; + typedef LOG4CPLUS_STREAM_NAMESPACE::istream tistream; + static tostream &tcout = LOG4CPLUS_STREAM_NAMESPACE::cout; + static tostream &tcerr = LOG4CPLUS_STREAM_NAMESPACE::cerr; + typedef LOG4CPLUS_STREAM_NAMESPACE::ostringstream tostringstream; + } +#endif // UNICODE + +#endif // LOG4CPLUS_STREAMS_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/syslogappender.h b/libs/log4cplus/include/log4cplus/syslogappender.h new file mode 100644 index 0000000..7a17774 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/syslogappender.h @@ -0,0 +1,82 @@ +// Module: Log4CPLUS +// File: syslogappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_SYSLOG_APPENDER_HEADER_ +#define _LOG4CPLUS_SYSLOG_APPENDER_HEADER_ + +#include + +#if defined(LOG4CPLUS_HAVE_SYSLOG_H) && !defined(_WIN32) +#include + +namespace log4cplus { + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
ident
+ *
First argument to openlog(), a string that + * will be prepended to every message.
+ * + *
facility
+ *
Facility is used in combination with syslog level in first + * argument to syslog(). It can be one of the supported facility + * names (case insensitive), e.g. auth, cron, kern, mail, news + * etc.
+ *
+ */ + class LOG4CPLUS_EXPORT SysLogAppender : public Appender { + public: + // Ctors + SysLogAppender(const tstring& ident); + SysLogAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~SysLogAppender(); + + // Methods + virtual void close(); + + protected: + virtual int getSysLogLevel(const LogLevel& ll) const; + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + tstring ident; + int facility; + + private: + // Disallow copying of instances of this class + SysLogAppender(const SysLogAppender&); + SysLogAppender& operator=(const SysLogAppender&); + + std::string identStr; + }; + +} // end namespace log4cplus + +#endif // defined(HAVE_SYSLOG_H) + +#endif // _LOG4CPLUS_SYSLOG_APPENDER_HEADER_ + diff --git a/libs/log4cplus/include/log4cplus/tstring.h b/libs/log4cplus/include/log4cplus/tstring.h new file mode 100644 index 0000000..f419828 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/tstring.h @@ -0,0 +1,85 @@ +// Module: Log4CPLUS +// File: tstring.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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. + +/** @file */ + +#ifndef LOG4CPLUS_TSTRING_HEADER_ +#define LOG4CPLUS_TSTRING_HEADER_ + +#include +#include + +#ifdef UNICODE +# ifdef LOG4CPLUS_WORKING_LOCALE +# include +# endif // LOG4CPLUS_WORKING_LOCALE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) + + +#ifdef UNICODE +namespace log4cplus { + typedef wchar_t tchar; + typedef std::wstring tstring; + + namespace helpers { +#ifdef LOG4CPLUS_WORKING_LOCALE + LOG4CPLUS_EXPORT std::string tostring(const std::wstring&, + std::locale const & = std::locale ()); + + LOG4CPLUS_EXPORT std::string tostring (wchar_t const *, + std::locale const & = std::locale ()); + + LOG4CPLUS_EXPORT std::wstring towstring(const std::string&, + std::locale const & = std::locale ()); + + LOG4CPLUS_EXPORT std::wstring towstring(char const *, + std::locale const & = std::locale ()); + +#else // LOG4CPLUS_WORKING_LOCALE + LOG4CPLUS_EXPORT std::string tostring(const std::wstring&); + LOG4CPLUS_EXPORT std::string tostring(wchar_t const *); + LOG4CPLUS_EXPORT std::wstring towstring(const std::string&); + LOG4CPLUS_EXPORT std::wstring towstring(char const *); +#endif // LOG4CPLUS_WORKING_LOCALE + } + +} + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) log4cplus::helpers::tostring(STRING) + +#else // UNICODE +namespace log4cplus { + typedef char tchar; + typedef std::string tstring; +} + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) std::string(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) STRING +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) STRING + +#endif // UNICODE + +#endif // LOG4CPLUS_TSTRING_HEADER_ diff --git a/libs/log4cplus/include/log4cplus/version.h b/libs/log4cplus/include/log4cplus/version.h new file mode 100644 index 0000000..618eb45 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/version.h @@ -0,0 +1,49 @@ +// Copyright (C) 2010, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#if ! defined (LOG4CPLUS_VERSION_H) +#define LOG4CPLUS_VERSION_H + +#include + + +#define LOG4CPLUS_MAKE_VERSION(major, minor, point) \ + (major * 1000 * 1000u + minor * 1000u + point) + +#define LOG4CPLUS_MAKE_VERSION_STR(major, minor, point) \ + #major "." #minor "." #point + +#define LOG4CPLUS_VERSION LOG4CPLUS_MAKE_VERSION(1, 0, 4) +#define LOG4CPLUS_VERSION_STR LOG4CPLUS_MAKE_VERSION_STR(1, 0, 4) + + +namespace log4cplus +{ + +extern LOG4CPLUS_EXPORT unsigned const version; +extern LOG4CPLUS_EXPORT char const versionStr[]; + +} + +#endif diff --git a/libs/log4cplus/include/log4cplus/win32consoleappender.h b/libs/log4cplus/include/log4cplus/win32consoleappender.h new file mode 100644 index 0000000..2cd93ca --- /dev/null +++ b/libs/log4cplus/include/log4cplus/win32consoleappender.h @@ -0,0 +1,77 @@ +// Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_WIN32CONSOLEAPPENDER_H +#define LOG4CPLUS_WIN32CONSOLEAPPENDER_H + + +#include +#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) + +#include +#include + + +namespace log4cplus +{ + + /** + * Prints events to Win32 console. + * + *

Properties

+ *
+ *
AllocConsole
+ *
This boolean property specifies whether or not this appender + * will try to allocate new console using the + * AllocConsole() Win32 function.
+ * + *
+ */ + class LOG4CPLUS_EXPORT Win32ConsoleAppender + : public Appender + { + public: + explicit Win32ConsoleAppender (bool allocConsole = true); + Win32ConsoleAppender (helpers::Properties const & properties); + virtual ~Win32ConsoleAppender (); + + virtual void close (); + + protected: + virtual void append (spi::InternalLoggingEvent const &); + + void write_handle (HANDLE, tchar const *, size_t); + void write_console (HANDLE, tchar const *, size_t); + + bool alloc_console; + + private: + Win32ConsoleAppender (Win32ConsoleAppender const &); + Win32ConsoleAppender & operator = (Win32ConsoleAppender const &); + }; + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_WIN32CONSOLEAPPENDER_H diff --git a/libs/log4cplus/include/log4cplus/win32debugappender.h b/libs/log4cplus/include/log4cplus/win32debugappender.h new file mode 100644 index 0000000..5713091 --- /dev/null +++ b/libs/log4cplus/include/log4cplus/win32debugappender.h @@ -0,0 +1,65 @@ +// Module: Log4CPLUS +// File: win32debugappender.h +// Created: 12/2003 +// Author: Eduardo Francos, Odalio SARL +// +// +// Copyright 2003-2010 Odalio SARL +// +// 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. + +/** @file */ + +#ifndef _LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ +#define _LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ + +#include +#if defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) + +#include +#include + + +namespace log4cplus { + + /** + * Prints log events using OutputDebugString(). + */ + class LOG4CPLUS_EXPORT Win32DebugAppender + : public Appender + { + public: + // Ctors + Win32DebugAppender(); + Win32DebugAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~Win32DebugAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + Win32DebugAppender(const Win32DebugAppender&); + Win32DebugAppender& operator=(const Win32DebugAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_WIN32_CONSOLE +#endif // _LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ + diff --git a/libs/log4cplus/src/appender.cxx b/libs/log4cplus/src/appender.cxx new file mode 100644 index 0000000..c1999cc --- /dev/null +++ b/libs/log4cplus/src/appender.cxx @@ -0,0 +1,266 @@ +// Module: Log4CPLUS +// File: appender.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include +#include + +using namespace log4cplus; +using namespace log4cplus::helpers; +using namespace log4cplus::spi; + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::ErrorHandler dtor +/////////////////////////////////////////////////////////////////////////////// + +ErrorHandler::~ErrorHandler() +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::OnlyOnceErrorHandler public methods +/////////////////////////////////////////////////////////////////////////////// + +void +OnlyOnceErrorHandler::error(const log4cplus::tstring& err) +{ + if(firstTime) { + getLogLog().error(err); + firstTime = false; + } +} + + + +void +OnlyOnceErrorHandler::reset() +{ + firstTime = true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::Appender ctors +/////////////////////////////////////////////////////////////////////////////// + +Appender::Appender() + : layout(new SimpleLayout()), + name( LOG4CPLUS_TEXT("") ), + threshold(NOT_SET_LOG_LEVEL), + errorHandler(new OnlyOnceErrorHandler()), + closed(false) +{ +} + + + +Appender::Appender(const log4cplus::helpers::Properties properties) + : layout(new SimpleLayout()), + name( LOG4CPLUS_TEXT("") ), + threshold(NOT_SET_LOG_LEVEL), + errorHandler(new OnlyOnceErrorHandler()), + closed(false) +{ + if(properties.exists( LOG4CPLUS_TEXT("layout") )) { + log4cplus::tstring factoryName = properties.getProperty( LOG4CPLUS_TEXT("layout") ); + LayoutFactory* factory = getLayoutFactoryRegistry().get(factoryName); + if(factory == 0) { + getLogLog().error( LOG4CPLUS_TEXT("Cannot find LayoutFactory: \"") + + factoryName + + LOG4CPLUS_TEXT("\"") ); + return; + } + + Properties layoutProperties = + properties.getPropertySubset( LOG4CPLUS_TEXT("layout.") ); + try { + std::auto_ptr newLayout(factory->createObject(layoutProperties)); + if(newLayout.get() == 0) { + getLogLog().error( LOG4CPLUS_TEXT("Failed to create appender: ") + + factoryName); + } + else { + layout = newLayout; + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("Error while creating Layout: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + return; + } + + } + + // Support for appender.Threshold in properties configuration file + if(properties.exists(LOG4CPLUS_TEXT("Threshold"))) { + tstring tmp = properties.getProperty(LOG4CPLUS_TEXT("Threshold")); + tmp = log4cplus::helpers::toUpper(tmp); + threshold = log4cplus::getLogLevelManager().fromString(tmp); + } + + // Configure the filters + Properties filterProps = properties.getPropertySubset( LOG4CPLUS_TEXT("filters.") ); + int filterCount = 0; + FilterPtr filterChain; + tstring filterName, factoryName; + while( filterProps.exists(filterName = convertIntegerToString(++filterCount)) ) { + factoryName = filterProps.getProperty(filterName); + FilterFactory* factory = getFilterFactoryRegistry().get(factoryName); + + if(factory == 0) { + tstring err = LOG4CPLUS_TEXT("Appender::ctor()- Cannot find FilterFactory: "); + getLogLog().error(err + factoryName); + continue; + } + FilterPtr tmp_filter = factory->createObject + (filterProps.getPropertySubset(filterName + LOG4CPLUS_TEXT("."))); + if(tmp_filter.get() == 0) { + tstring err = LOG4CPLUS_TEXT("Appender::ctor()- Failed to create filter: "); + getLogLog().error(err + filterName); + } + if(filterChain.get() == 0) { + filterChain = tmp_filter; + } + else { + filterChain->appendFilter(tmp_filter); + } + } + setFilter(filterChain); +} + + +Appender::~Appender() +{ } + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::Appender public methods +/////////////////////////////////////////////////////////////////////////////// + +void +Appender::destructorImpl() +{ + getLogLog().debug( LOG4CPLUS_TEXT("Destroying appender named [") + + name + + LOG4CPLUS_TEXT("].")); + + // An appender might be closed then destroyed. There is no + // point in closing twice. + if(closed) { + return; + } + + close(); + closed = true; +} + + + +void +Appender::doAppend(const log4cplus::spi::InternalLoggingEvent& event) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ) + if(closed) { + getLogLog().error( LOG4CPLUS_TEXT("Attempted to append to closed appender named [") + + name + + LOG4CPLUS_TEXT("].")); + return; + } + + if(!isAsSevereAsThreshold(event.getLogLevel())) { + return; + } + + if(checkFilter(filter.get(), event) == DENY) { + return; + } + + append(event); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +log4cplus::tstring +Appender::getName() +{ + return name; +} + + + +void +Appender::setName(const log4cplus::tstring& name_) +{ + this->name = name_; +} + + +ErrorHandler* +Appender::getErrorHandler() +{ + return errorHandler.get(); +} + + + +void +Appender::setErrorHandler(std::auto_ptr eh) +{ + if(eh.get() == NULL) { + // We do not throw exception here since the cause is probably a + // bad config file. + getLogLog().warn(LOG4CPLUS_TEXT("You have tried to set a null error-handler.")); + return; + } + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ) + this->errorHandler = eh; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +void +Appender::setLayout(std::auto_ptr lo) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ) + this->layout = lo; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +Layout* +Appender::getLayout() +{ + return layout.get(); +} + + diff --git a/libs/log4cplus/src/appenderattachableimpl.cxx b/libs/log4cplus/src/appenderattachableimpl.cxx new file mode 100644 index 0000000..123102b --- /dev/null +++ b/libs/log4cplus/src/appenderattachableimpl.cxx @@ -0,0 +1,177 @@ +// Module: Log4CPLUS +// File: appenderattachableimpl.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include + +#include + + +namespace log4cplus +{ + + +namespace spi +{ + + +AppenderAttachable::~AppenderAttachable() +{ } + + +} // namespace spi + + +namespace helpers +{ + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::AppenderAttachableImpl ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +AppenderAttachableImpl::AppenderAttachableImpl() + : appender_list_mutex(LOG4CPLUS_MUTEX_CREATE) +{ +} + + +AppenderAttachableImpl::~AppenderAttachableImpl() +{ + LOG4CPLUS_MUTEX_FREE( appender_list_mutex ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::AppenderAttachableImpl public methods +/////////////////////////////////////////////////////////////////////////////// + +void +AppenderAttachableImpl::addAppender(SharedAppenderPtr newAppender) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( appender_list_mutex ) + if(newAppender == NULL) { + getLogLog().warn( LOG4CPLUS_TEXT("Tried to add NULL appender") ); + return; + } + + ListType::iterator it = + std::find(appenderList.begin(), appenderList.end(), newAppender); + if(it == appenderList.end()) { + appenderList.push_back(newAppender); + } + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +AppenderAttachableImpl::ListType +AppenderAttachableImpl::getAllAppenders() +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( appender_list_mutex ) + return appenderList; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +SharedAppenderPtr +AppenderAttachableImpl::getAppender(const log4cplus::tstring& name) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( appender_list_mutex ) + for(ListType::iterator it=appenderList.begin(); + it!=appenderList.end(); + ++it) + { + if((*it)->getName() == name) { + return *it; + } + } + + return SharedAppenderPtr(NULL); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +void +AppenderAttachableImpl::removeAllAppenders() +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( appender_list_mutex ) + appenderList.erase(appenderList.begin(), appenderList.end()); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +void +AppenderAttachableImpl::removeAppender(SharedAppenderPtr appender) +{ + if(appender == NULL) { + getLogLog().warn( LOG4CPLUS_TEXT("Tried to remove NULL appender") ); + return; + } + + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( appender_list_mutex ) + ListType::iterator it = + std::find(appenderList.begin(), appenderList.end(), appender); + if(it != appenderList.end()) { + appenderList.erase(it); + } + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +void +AppenderAttachableImpl::removeAppender(const log4cplus::tstring& name) +{ + removeAppender(getAppender(name)); +} + + + +int +AppenderAttachableImpl::appendLoopOnAppenders(const spi::InternalLoggingEvent& event) const +{ + int count = 0; + + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( appender_list_mutex ) + for(ListType::const_iterator it=appenderList.begin(); + it!=appenderList.end(); + ++it) + { + ++count; + (*it)->doAppend(event); + } + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; + + return count; +} + + +} // namespace helpers + + +} // namespace log4cplus diff --git a/libs/log4cplus/src/configurator.cxx b/libs/log4cplus/src/configurator.cxx new file mode 100644 index 0000000..5eaa4fd --- /dev/null +++ b/libs/log4cplus/src/configurator.cxx @@ -0,0 +1,778 @@ +// Module: LOG4CPLUS +// File: configurator.cxx +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LOG4CPLUS_HAVE_SYS_STAT_H +#include +#endif + +#ifdef LOG4CPLUS_HAVE_STDLIB_H +#include +#endif +#if defined (WIN32) +#include +#endif +#if defined (_WIN32_WCE) +#include +#endif + +#include +#include +#include + + +namespace log4cplus +{ + +using namespace log4cplus::helpers; +using namespace log4cplus::spi; + + +void initializeLog4cplus(); + + +namespace +{ + static tchar const DELIM_START[] = LOG4CPLUS_TEXT("${"); + static tchar const DELIM_STOP[] = LOG4CPLUS_TEXT("}"); + static size_t const DELIM_START_LEN = 2; + static size_t const DELIM_STOP_LEN = 1; + + + static + void + get_env_var (tstring & value, tstring const & name) + { +#if defined (_WIN32_WCE) + // Nothing to do here. Windows CE does not have environment variables. + +#elif defined (WIN32) && defined (UNICODE) + tchar const * val = _wgetenv (name.c_str ()); + if (val) + value = val; + +#else + char const * val + = std::getenv (LOG4CPLUS_TSTRING_TO_STRING (name).c_str ()); + if (val) + value = LOG4CPLUS_STRING_TO_TSTRING (val); + +#endif + } + + + struct file_info + { + Time mtime; + bool is_link; + }; + + + static + int + get_file_info (file_info * fi, tstring const & name) + { +#if defined (_WIN32_WCE) + WIN32_FILE_ATTRIBUTE_DATA fad; + BOOL ret = GetFileAttributesEx (name.c_str (), GetFileExInfoStandard, &fad); + if (! ret) + return -1; + + SYSTEMTIME systime; + ret = FileTimeToSystemTime (&fad.ftLastWriteTime, &systime); + if (! ret) + return -1; + + helpers::tm tm; + tm.tm_isdst = 0; + tm.tm_yday = 0; + tm.tm_wday = systime.wDayOfWeek; + tm.tm_year = systime.wYear - 1900; + tm.tm_mon = systime.wMonth - 1; + tm.tm_mday = systime.wDay; + tm.tm_hour = systime.wHour; + tm.tm_min = systime.wMinute; + tm.tm_sec = systime.wSecond; + + fi->mtime.setTime (&tm); + fi->is_link = false; + +#elif defined (_WIN32) + struct _stat fileStatus; + if (_tstat (name.c_str (), &fileStatus) == -1) + return -1; + + fi->mtime = Time (fileStatus.st_mtime); + fi->is_link = false; + +#else + struct stat fileStatus; + if (stat (LOG4CPLUS_TSTRING_TO_STRING (name).c_str (), + &fileStatus) == -1) + return -1; + fi->mtime = Time (fileStatus.st_mtime); + fi->is_link = S_ISLNK (fileStatus.st_mode); + +#endif + + return 0; + } + + + /** + * Perform variable substitution in string val from + * environment variables. + * + *

The variable substitution delimeters are ${ and }. + * + *

For example, if the System properties contains "key=value", then + * the call + *

+     * string s;
+     * substEnvironVars(s, "Value of key is ${key}.");
+     * 
+ * + * will set the variable s to "Value of key is value.". + * + *

If no value could be found for the specified key, then + * substitution defaults to the empty string. + * + *

For example, if there is no environment variable "inexistentKey", + * then the call + * + *

+     * string s;
+     * substEnvironVars(s, "Value of inexistentKey is [${inexistentKey}]");
+     * 
+ * will set s to "Value of inexistentKey is []" + * + * @param val The string on which variable substitution is performed. + * @param dest The result. + */ + static + bool + substVars (tstring & dest, const tstring & val, Properties const & props, + helpers::LogLog& loglog, unsigned flags) + { + tstring::size_type i = 0; + tstring::size_type var_start, var_end; + tstring pattern (val); + tstring key; + tstring replacement; + bool changed = false; + bool const empty_vars + = !! (flags & PropertyConfigurator::fAllowEmptyVars); + bool const shadow_env + = !! (flags & PropertyConfigurator::fShadowEnvironment); + bool const rec_exp + = !! (flags & PropertyConfigurator::fRecursiveExpansion); + + while (true) + { + // Find opening paren of variable substitution. + var_start = pattern.find(DELIM_START, i); + if (var_start == tstring::npos) + { + dest = pattern; + return changed; + } + + // Find closing paren of variable substitution. + var_end = pattern.find(DELIM_STOP, var_start); + if (var_end == tstring::npos) + { + tostringstream buffer; + buffer << '"' << pattern + << "\" has no closing brace. " + << "Opening brace at position " << var_start << "."; + loglog.error(buffer.str()); + dest = val; + return false; + } + + key.assign (pattern, var_start + DELIM_START_LEN, + var_end - (var_start + DELIM_START_LEN)); + replacement.clear (); + if (shadow_env) + replacement = props.getProperty (key); + if (! shadow_env || (! empty_vars && replacement.empty ())) + get_env_var (replacement, key); + + if (empty_vars || ! replacement.empty ()) + { + // Substitute the variable with its value in place. + pattern.replace (var_start, var_end - var_start + DELIM_STOP_LEN, + replacement); + changed = true; + if (rec_exp) + // Retry expansion on the same spot. + continue; + else + // Move beyond the just substitued part. + i = var_start + replacement.size (); + } + else + // Nothing has been subtituted, just move beyond the + // unexpanded variable. + i = var_end + DELIM_STOP_LEN; + } // end while loop + + } // end substVars() + +} // namespace + + + +////////////////////////////////////////////////////////////////////////////// +// PropertyConfigurator ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +PropertyConfigurator::PropertyConfigurator(const tstring& propertyFile, + Hierarchy& h_, unsigned flags_) + : h(h_) + , propertyFilename(propertyFile) + , properties(propertyFile) + , flags (flags_) +{ + init(); +} + + +PropertyConfigurator::PropertyConfigurator(const helpers::Properties& props, + Hierarchy& h_, unsigned flags_) + : h(h_) + , propertyFilename( LOG4CPLUS_TEXT("UNAVAILABLE") ) + , properties( props ) + , flags (flags_) +{ + init(); +} + + +PropertyConfigurator::PropertyConfigurator(tistream& propertyStream, + Hierarchy& h_, unsigned flags_) + : h(h_) + , propertyFilename( LOG4CPLUS_TEXT("UNAVAILABLE") ) + , properties(propertyStream) + , flags (flags_) +{ + init(); +} + + +void +PropertyConfigurator::init() +{ + replaceEnvironVariables(); + properties = properties.getPropertySubset( LOG4CPLUS_TEXT("log4cplus.") ); +} + + +PropertyConfigurator::~PropertyConfigurator() +{ +} + + + +////////////////////////////////////////////////////////////////////////////// +// PropertyConfigurator static methods +////////////////////////////////////////////////////////////////////////////// + +void +PropertyConfigurator::doConfigure(const tstring& file, Hierarchy& h, + unsigned flags) +{ + PropertyConfigurator tmp(file, h, flags); + tmp.configure(); +} + + + +////////////////////////////////////////////////////////////////////////////// +// PropertyConfigurator public methods +////////////////////////////////////////////////////////////////////////////// + +void +PropertyConfigurator::configure() +{ + // Configure log4cplus internals. + log4cplus::tstring val = properties.getProperty ( + LOG4CPLUS_TEXT ("configDebug"), LOG4CPLUS_TEXT ("false")); + getLogLog ().setInternalDebugging ( + helpers::toLower (val) == LOG4CPLUS_TEXT ("true")); + + initializeLog4cplus(); + configureAppenders(); + configureLoggers(); + configureAdditivity(); + + // Erase the appenders so that we are not artificially keeping them "alive". + appenders.clear (); +} + + +helpers::Properties const & +PropertyConfigurator::getProperties () const +{ + return properties; +} + + +log4cplus::tstring const & +PropertyConfigurator::getPropertyFilename () const +{ + return propertyFilename; +} + + +////////////////////////////////////////////////////////////////////////////// +// PropertyConfigurator protected methods +////////////////////////////////////////////////////////////////////////////// + +void +PropertyConfigurator::reconfigure() +{ + properties = Properties(propertyFilename); + init(); + configure(); +} + + +void +PropertyConfigurator::replaceEnvironVariables() +{ + tstring val, subKey, subVal; + std::vector keys; + bool const rec_exp + = !! (flags & PropertyConfigurator::fRecursiveExpansion); + bool changed; + + do + { + changed = false; + properties.propertyNames().swap (keys); + for (std::vector::const_iterator it = keys.begin(); + it != keys.end(); ++it) + { + tstring const & key = *it; + val = properties.getProperty(key); + + subKey.clear (); + if (substVars(subKey, key, properties, getLogLog(), flags)) + { + properties.removeProperty(key); + properties.setProperty(subKey, val); + changed = true; + } + + subVal.clear (); + if (substVars(subVal, val, properties, getLogLog(), flags)) + { + properties.setProperty(subKey, subVal); + changed = true; + } + } + } + while (changed && rec_exp); +} + + + +void +PropertyConfigurator::configureLoggers() +{ + if(properties.exists( LOG4CPLUS_TEXT("rootLogger") )) + { + Logger root = h.getRoot(); + configureLogger(root, + properties.getProperty(LOG4CPLUS_TEXT("rootLogger"))); + } + + Properties loggerProperties + = properties.getPropertySubset(LOG4CPLUS_TEXT("logger.")); + std::vector loggers = loggerProperties.propertyNames(); + for(std::vector::iterator it=loggers.begin(); it!=loggers.end(); + ++it) + { + Logger log = getLogger(*it); + configureLogger(log, loggerProperties.getProperty(*it)); + } +} + + + +void +PropertyConfigurator::configureLogger(Logger logger, const tstring& config) +{ + // Remove all spaces from config + tstring configString; + remove_copy_if(config.begin(), config.end(), + string_append_iterator(configString), + std::bind1st(std::equal_to(), LOG4CPLUS_TEXT(' '))); + + // "Tokenize" configString + std::vector tokens; + tokenize(configString, ',', std::back_inserter(tokens)); + + if(tokens.empty()) { + getLogLog().error( + LOG4CPLUS_TEXT("PropertyConfigurator::configureLogger()") + LOG4CPLUS_TEXT("- Invalid config string(Logger = ") + + logger.getName() + + LOG4CPLUS_TEXT("): \"") + + config + + LOG4CPLUS_TEXT("\"")); + return; + } + + // Set the loglevel + tstring loglevel = tokens[0]; + if (loglevel != LOG4CPLUS_TEXT("INHERITED")) + logger.setLogLevel( getLogLevelManager().fromString(loglevel) ); + else + logger.setLogLevel (NOT_SET_LOG_LEVEL); + + // Remove all existing appenders first so that we do not duplicate output. + logger.removeAllAppenders (); + + // Set the Appenders + for(std::vector::size_type j=1; jsecond); + } +} + + + +void +PropertyConfigurator::configureAppenders() +{ + Properties appenderProperties = + properties.getPropertySubset(LOG4CPLUS_TEXT("appender.")); + std::vector appendersProps = appenderProperties.propertyNames(); + tstring factoryName; + for(std::vector::iterator it=appendersProps.begin(); + it != appendersProps.end(); ++it) + { + if( it->find( LOG4CPLUS_TEXT('.') ) == tstring::npos ) + { + factoryName = appenderProperties.getProperty(*it); + AppenderFactory* factory + = getAppenderFactoryRegistry().get(factoryName); + if (factory == 0) + { + tstring err = + LOG4CPLUS_TEXT("PropertyConfigurator::configureAppenders()") + LOG4CPLUS_TEXT("- Cannot find AppenderFactory: "); + getLogLog().error(err + factoryName); + continue; + } + + Properties my_properties + = appenderProperties.getPropertySubset((*it) + + LOG4CPLUS_TEXT(".")); + try + { + SharedAppenderPtr appender = factory->createObject(my_properties); + if (appender.get() == 0) + { + tstring err = + LOG4CPLUS_TEXT("PropertyConfigurator::") + LOG4CPLUS_TEXT("configureAppenders()") + LOG4CPLUS_TEXT("- Failed to create appender: "); + getLogLog().error(err + *it); + } + else + { + appender->setName(*it); + appenders[*it] = appender; + } + } + catch(std::exception& e) + { + tstring err = + LOG4CPLUS_TEXT("PropertyConfigurator::") + LOG4CPLUS_TEXT("configureAppenders()") + LOG4CPLUS_TEXT("- Error while creating Appender: "); + getLogLog().error(err + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + } + } // end for loop +} + + +void +PropertyConfigurator::configureAdditivity() +{ + Properties additivityProperties = + properties.getPropertySubset(LOG4CPLUS_TEXT("additivity.")); + std::vector additivitysProps = additivityProperties.propertyNames(); + + tstring actualValue; + tstring value; + + for(std::vector::const_iterator it = additivitysProps.begin(); + it != additivitysProps.end(); ++it) + { + Logger logger = getLogger(*it); + actualValue = additivityProperties.getProperty(*it); + value = toLower(actualValue); + + if(value == LOG4CPLUS_TEXT("true")) + logger.setAdditivity(true); + else if(value == LOG4CPLUS_TEXT("false")) + logger.setAdditivity(false); + else + getLogLog().warn( LOG4CPLUS_TEXT("Invalid Additivity value: \"") + + actualValue + + LOG4CPLUS_TEXT("\"")); + } +} + + + +Logger +PropertyConfigurator::getLogger(const tstring& name) +{ + return h.getInstance(name); +} + + +void +PropertyConfigurator::addAppender(Logger &logger, SharedAppenderPtr& appender) +{ + logger.addAppender(appender); +} + + + +////////////////////////////////////////////////////////////////////////////// +// BasicConfigurator ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +BasicConfigurator::BasicConfigurator(Hierarchy& h_) + : PropertyConfigurator( LOG4CPLUS_TEXT(""), h_ ) +{ + properties.setProperty(LOG4CPLUS_TEXT("rootLogger"), + LOG4CPLUS_TEXT("DEBUG, STDOUT")); + properties.setProperty(LOG4CPLUS_TEXT("appender.STDOUT"), + LOG4CPLUS_TEXT("log4cplus::ConsoleAppender")); +} + + + + +BasicConfigurator::~BasicConfigurator() +{ +} + + +////////////////////////////////////////////////////////////////////////////// +// BasicConfigurator static methods +////////////////////////////////////////////////////////////////////////////// + +void +BasicConfigurator::doConfigure(Hierarchy& h) +{ + BasicConfigurator tmp(h); + tmp.configure(); +} + + +#if !defined(LOG4CPLUS_SINGLE_THREADED) + +////////////////////////////////////////////////////////////////////////////// +// ConfigurationWatchDogThread implementation +////////////////////////////////////////////////////////////////////////////// + +class ConfigurationWatchDogThread + : public thread::AbstractThread, + public PropertyConfigurator +{ +public: + ConfigurationWatchDogThread(const tstring& file, unsigned int millis) + : PropertyConfigurator(file) + , waitMillis(waitMillis < 1000 ? 1000 : millis) + , shouldTerminate(false) + , lock(NULL) + { } + + virtual ~ConfigurationWatchDogThread () + { } + + void terminate () + { + shouldTerminate.signal (); + join (); + } + +protected: + virtual void run(); + virtual Logger getLogger(const tstring& name); + virtual void addAppender(Logger &logger, SharedAppenderPtr& appender); + + bool checkForFileModification(Time & mtime); + void updateLastModTime(Time const & mtime); + +private: + unsigned int const waitMillis; + thread::ManualResetEvent shouldTerminate; + Time lastModTime; + HierarchyLocker* lock; +}; + + +void +ConfigurationWatchDogThread::run() +{ + Time mtime; + + // Initialize last modification time. + checkForFileModification (mtime); + updateLastModTime (mtime); + + while (! shouldTerminate.timed_wait (waitMillis)) + { + bool modified = checkForFileModification(mtime); + if(modified) { + // Lock the Hierarchy + HierarchyLocker theLock(h); + lock = &theLock; + + // reconfigure the Hierarchy + theLock.resetConfiguration(); + reconfigure(); + updateLastModTime(mtime); + + // release the lock + lock = NULL; + } + } +} + + +Logger +ConfigurationWatchDogThread::getLogger(const tstring& name) +{ + if(lock) + return lock->getInstance(name); + else + return PropertyConfigurator::getLogger(name); +} + + +void +ConfigurationWatchDogThread::addAppender(Logger& logger, + SharedAppenderPtr& appender) +{ + if(lock) + lock->addAppender(logger, appender); + else + PropertyConfigurator::addAppender(logger, appender); +} + + +bool +ConfigurationWatchDogThread::checkForFileModification(Time & mtime) +{ + file_info fi; + + if (get_file_info (&fi, propertyFilename.c_str ()) != 0) + return false; + + mtime = fi.mtime; + bool modified = mtime != lastModTime; + +#if defined(LOG4CPLUS_HAVE_LSTAT) + if (!modified && fi.is_link) + { + struct stat fileStatus; + if (lstat(LOG4CPLUS_TSTRING_TO_STRING(propertyFilename).c_str(), + &fileStatus) == -1) + return false; + + mtime = Time (fileStatus.st_mtime); + modified = mtime != lastModTime; + } +#endif + + return modified; +} + + +void +ConfigurationWatchDogThread::updateLastModTime(Time const & mtime) +{ + lastModTime = mtime; +} + + + +////////////////////////////////////////////////////////////////////////////// +// PropertyConfiguratorWatchDog ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +ConfigureAndWatchThread::ConfigureAndWatchThread(const tstring& file, + unsigned int millis) + : watchDogThread(0) +{ + watchDogThread = new ConfigurationWatchDogThread(file, millis); + watchDogThread->addReference (); + watchDogThread->configure(); + watchDogThread->start(); +} + + +ConfigureAndWatchThread::~ConfigureAndWatchThread() +{ + if (watchDogThread) + { + watchDogThread->terminate(); + watchDogThread->removeReference (); + } +} + + +#endif + + +} // namespace log4cplus diff --git a/libs/log4cplus/src/consoleappender.cxx b/libs/log4cplus/src/consoleappender.cxx new file mode 100644 index 0000000..8939223 --- /dev/null +++ b/libs/log4cplus/src/consoleappender.cxx @@ -0,0 +1,101 @@ +// Module: Log4CPLUS +// File: consoleappender.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include + +using namespace std; +using namespace log4cplus::helpers; + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::ConsoleAppender ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +log4cplus::ConsoleAppender::ConsoleAppender(bool logToStdErr_, bool immediateFlush_) +: logToStdErr(logToStdErr_), + immediateFlush(immediateFlush_) +{ +} + + + +log4cplus::ConsoleAppender::ConsoleAppender(const log4cplus::helpers::Properties properties) +: Appender(properties), + logToStdErr(false), + immediateFlush(false) +{ + tstring val = toLower(properties.getProperty(LOG4CPLUS_TEXT("logToStdErr"))); + if(val == LOG4CPLUS_TEXT("true")) { + logToStdErr = true; + } + if(properties.exists( LOG4CPLUS_TEXT("ImmediateFlush") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("ImmediateFlush") ); + immediateFlush = (toLower(tmp) == LOG4CPLUS_TEXT("true")); + } +} + + + +log4cplus::ConsoleAppender::~ConsoleAppender() +{ + destructorImpl(); +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::ConsoleAppender public methods +////////////////////////////////////////////////////////////////////////////// + +void +log4cplus::ConsoleAppender::close() +{ + getLogLog().debug(LOG4CPLUS_TEXT("Entering ConsoleAppender::close()..")); + closed = true; +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::ConsoleAppender protected methods +////////////////////////////////////////////////////////////////////////////// + +// Normally, append() methods do not need to be locked since they are +// called by doAppend() which performs the locking. However, this locks +// on the LogLog instance, so we don't have multiple threads writing to +// tcout and tcerr +void +log4cplus::ConsoleAppender::append(const spi::InternalLoggingEvent& event) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( getLogLog().mutex ) + log4cplus::tostream& output = (logToStdErr ? tcerr : tcout); + layout->formatAndAppend(output, event); + if(immediateFlush) { + output.flush(); + } + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + diff --git a/libs/log4cplus/src/factory.cxx b/libs/log4cplus/src/factory.cxx new file mode 100644 index 0000000..3144cd1 --- /dev/null +++ b/libs/log4cplus/src/factory.cxx @@ -0,0 +1,220 @@ +// Module: Log4CPLUS +// File: factory.cxx +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (_WIN32) +# if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG) +# include +# endif +# if defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) +# include +# endif +# include +#endif + + +using namespace log4cplus; +using namespace log4cplus::helpers; +using namespace log4cplus::spi; + + +/////////////////////////////////////////////////////////////////////////////// +// LOCAL file class definitions +/////////////////////////////////////////////////////////////////////////////// + +namespace log4cplus { + +namespace spi { + + BaseFactory::~BaseFactory() + { } + + + AppenderFactory::AppenderFactory() + { } + + AppenderFactory::~AppenderFactory() + { } + + + LayoutFactory::LayoutFactory() + { } + + LayoutFactory::~LayoutFactory() + { } + + + FilterFactory::FilterFactory() + { } + + FilterFactory::~FilterFactory() + { } + + + LoggerFactory::~LoggerFactory() + { } + + +} // namespace spi + + +namespace +{ + + +template +class LocalFactoryBase + : public ProductFactoryBase +{ +public: + LocalFactoryBase (tchar const * n) + : name (n) + { } + + virtual log4cplus::tstring getTypeName() + { + return name; + } + +private: + log4cplus::tstring name; +}; + + +template +class FactoryTempl + : public LocalFactoryBase +{ +public: + typedef typename ProductFactoryBase::ProductPtr ProductPtr; + + FactoryTempl (tchar const * n) + : LocalFactoryBase (n) + { } + + virtual ProductPtr createObject (Properties const & props) + { + return ProductPtr (new LocalProduct (props)); + } +}; + + +} // namespace + + +#define REG_PRODUCT(reg, productprefix, productname, productns, productfact) \ +reg.put ( \ + std::auto_ptr ( \ + new FactoryTempl ( \ + LOG4CPLUS_TEXT(productprefix) \ + LOG4CPLUS_TEXT(#productname)))) + + +#define REG_APPENDER(reg, appendername) \ +REG_PRODUCT (reg, "log4cplus::", appendername, log4cplus::, AppenderFactory) + +#define REG_LAYOUT(reg, layoutname) \ +REG_PRODUCT (reg, "log4cplus::", layoutname, log4cplus::, LayoutFactory) + +#define REG_FILTER(reg, filtername) \ +REG_PRODUCT (reg, "log4cplus::spi::", filtername, spi::, FilterFactory) + + +void initializeFactoryRegistry() +{ + AppenderFactoryRegistry& reg = getAppenderFactoryRegistry(); + REG_APPENDER (reg, ConsoleAppender); + REG_APPENDER (reg, NullAppender); + REG_APPENDER (reg, FileAppender); + REG_APPENDER (reg, RollingFileAppender); + REG_APPENDER (reg, DailyRollingFileAppender); + REG_APPENDER (reg, SocketAppender); +#if defined(_WIN32) +# if defined(LOG4CPLUS_HAVE_NT_EVENT_LOG) + REG_APPENDER (reg, NTEventLogAppender); +# endif +# if defined(LOG4CPLUS_HAVE_WIN32_CONSOLE) + REG_APPENDER (reg, Win32ConsoleAppender); +# endif + REG_APPENDER (reg, Win32DebugAppender); +#elif defined(LOG4CPLUS_HAVE_SYSLOG_H) + REG_APPENDER (reg, SysLogAppender); +#endif + + LayoutFactoryRegistry& reg2 = getLayoutFactoryRegistry(); + REG_LAYOUT (reg2, SimpleLayout); + REG_LAYOUT (reg2, TTCCLayout); + REG_LAYOUT (reg2, PatternLayout); + + FilterFactoryRegistry& reg3 = getFilterFactoryRegistry(); + REG_FILTER (reg3, DenyAllFilter); + REG_FILTER (reg3, LogLevelMatchFilter); + REG_FILTER (reg3, LogLevelRangeFilter); + REG_FILTER (reg3, StringMatchFilter); +} + + + + +/////////////////////////////////////////////////////////////////////////////// +// public methods +/////////////////////////////////////////////////////////////////////////////// + +namespace spi +{ + + +AppenderFactoryRegistry& +getAppenderFactoryRegistry() +{ + static AppenderFactoryRegistry singleton; + return singleton; +} + + +LayoutFactoryRegistry& +getLayoutFactoryRegistry() +{ + static LayoutFactoryRegistry singleton; + return singleton; +} + + +FilterFactoryRegistry& +getFilterFactoryRegistry() +{ + static FilterFactoryRegistry singleton; + return singleton; +} + + +} // namespace spi + + +} // namespace log4cplus diff --git a/libs/log4cplus/src/fileappender.cxx b/libs/log4cplus/src/fileappender.cxx new file mode 100644 index 0000000..993a740 --- /dev/null +++ b/libs/log4cplus/src/fileappender.cxx @@ -0,0 +1,798 @@ +// Module: Log4CPLUS +// File: fileappender.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#if defined (__BORLANDC__) +// For _wrename() and _wremove() on Windows. +# include +#endif +#if ! defined (_WIN32_WCE) +#include +#endif +#include + +#if defined (_WIN32_WCE) +#undef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#include +#endif + + +namespace log4cplus +{ + +using helpers::Properties; +using helpers::Time; + + +const long MINIMUM_ROLLING_LOG_SIZE = 200*1024L; + + +/////////////////////////////////////////////////////////////////////////////// +// File LOCAL definitions +/////////////////////////////////////////////////////////////////////////////// + +namespace +{ + + +#if defined (_WIN32_WCE) +long const LOG4CPLUS_FILE_NOT_FOUND = ERROR_FILE_NOT_FOUND; +#else +long const LOG4CPLUS_FILE_NOT_FOUND = ENOENT; +#endif + + +static +long +file_rename (tstring const & src, tstring const & target) +{ +#if defined (_WIN32_WCE) + if (MoveFile (src.c_str (), target.c_str ())) + return 0; + else + return GetLastError (); + +#elif defined (UNICODE) && defined (WIN32) + if (_wrename (src.c_str (), target.c_str ()) == 0) + return 0; + else + return errno; + +#else + if (std::rename (LOG4CPLUS_TSTRING_TO_STRING (src).c_str (), + LOG4CPLUS_TSTRING_TO_STRING (target).c_str ()) == 0) + return 0; + else + return errno; + +#endif +} + + +static +long +file_remove (tstring const & src) +{ +#if defined (_WIN32_WCE) + if (DeleteFile (src.c_str ())) + return 0; + else + return GetLastError (); + +#elif defined (UNICODE) && defined (WIN32) + if (_wremove (src.c_str ()) == 0) + return 0; + else + return errno; + +#else + if (std::remove (LOG4CPLUS_TSTRING_TO_STRING (src).c_str ()) == 0) + return 0; + else + return errno; + +#endif +} + + +static +void +loglog_renaming_result (helpers::LogLog & loglog, tstring const & src, + tstring const & target, long ret) +{ + if (ret == 0) + { + loglog.debug ( + LOG4CPLUS_TEXT("Renamed file ") + + src + + LOG4CPLUS_TEXT(" to ") + + target); + } + else if (ret != LOG4CPLUS_FILE_NOT_FOUND) + { + tostringstream oss; + oss << LOG4CPLUS_TEXT("Failed to rename file from ") + << target + << LOG4CPLUS_TEXT(" to ") + << target + << LOG4CPLUS_TEXT("; error ") + << ret; + loglog.error (oss.str ()); + } +} + + +static +void +loglog_opening_result (helpers::LogLog & loglog, + log4cplus::tostream const & os, tstring const & filename) +{ + if (! os) + { + loglog.error ( + LOG4CPLUS_TEXT("Failed to open file ") + + filename); + } +} + + +static +void +rolloverFiles(const tstring& filename, unsigned int maxBackupIndex) +{ + helpers::SharedObjectPtr loglog + = helpers::LogLog::getLogLog(); + + // Delete the oldest file + tostringstream buffer; + buffer << filename << LOG4CPLUS_TEXT(".") << maxBackupIndex; + long ret = file_remove (buffer.str ()); + + tostringstream source_oss; + tostringstream target_oss; + + // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} + for (int i = maxBackupIndex - 1; i >= 1; --i) + { + source_oss.str(LOG4CPLUS_TEXT("")); + target_oss.str(LOG4CPLUS_TEXT("")); + + source_oss << filename << LOG4CPLUS_TEXT(".") << i; + target_oss << filename << LOG4CPLUS_TEXT(".") << (i+1); + + tstring const source (source_oss.str ()); + tstring const target (target_oss.str ()); + +#if defined (WIN32) + // Try to remove the target first. It seems it is not + // possible to rename over existing file. + ret = file_remove (target); +#endif + + ret = file_rename (source, target); + loglog_renaming_result (*loglog, source, target, ret); + } +} // end rolloverFiles() + +} + + +/////////////////////////////////////////////////////////////////////////////// +// FileAppender ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +FileAppender::FileAppender(const tstring& filename_, + LOG4CPLUS_OPEN_MODE_TYPE mode, bool immediateFlush_) + : immediateFlush(immediateFlush_) + , reopenDelay(1) + , bufferSize (0) + , buffer (0) +{ + init(filename_, mode); +} + + +FileAppender::FileAppender(const Properties& properties, + LOG4CPLUS_OPEN_MODE_TYPE mode) + : Appender(properties) + , immediateFlush(true) + , reopenDelay(1) + , bufferSize (0) + , buffer (0) +{ + bool append_ = (mode == std::ios::app); + tstring filename_ = properties.getProperty( LOG4CPLUS_TEXT("File") ); + if (filename_.empty()) + { + getErrorHandler()->error( LOG4CPLUS_TEXT("Invalid filename") ); + return; + } + if(properties.exists( LOG4CPLUS_TEXT("ImmediateFlush") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("ImmediateFlush") ); + immediateFlush = (helpers::toLower(tmp) == LOG4CPLUS_TEXT("true")); + } + if(properties.exists( LOG4CPLUS_TEXT("Append") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("Append") ); + append_ = (helpers::toLower(tmp) == LOG4CPLUS_TEXT("true")); + } + if(properties.exists( LOG4CPLUS_TEXT("ReopenDelay") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("ReopenDelay") ); + reopenDelay = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(tmp).c_str()); + } + if(properties.exists( LOG4CPLUS_TEXT("BufferSize") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("BufferSize") ); + bufferSize = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(tmp).c_str()); + } + + init(filename_, (append_ ? std::ios::app : std::ios::trunc)); +} + + + +void +FileAppender::init(const tstring& filename_, + LOG4CPLUS_OPEN_MODE_TYPE mode) +{ + this->filename = filename_; + open(mode); + + if (bufferSize != 0) + { + delete[] buffer; + buffer = new tchar[bufferSize]; + out.rdbuf ()->pubsetbuf (buffer, bufferSize); + } + + if(!out.good()) { + getErrorHandler()->error( LOG4CPLUS_TEXT("Unable to open file: ") + + filename); + return; + } + getLogLog().debug(LOG4CPLUS_TEXT("Just opened file: ") + filename); +} + + + +FileAppender::~FileAppender() +{ + destructorImpl(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// FileAppender public methods +/////////////////////////////////////////////////////////////////////////////// + +void +FileAppender::close() +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ) + out.close(); + delete[] buffer; + buffer = 0; + closed = true; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// FileAppender protected methods +/////////////////////////////////////////////////////////////////////////////// + +// This method does not need to be locked since it is called by +// doAppend() which performs the locking +void +FileAppender::append(const spi::InternalLoggingEvent& event) +{ + if(!out.good()) { + if(!reopen()) { + getErrorHandler()->error( LOG4CPLUS_TEXT("file is not open: ") + + filename); + return; + } + // Resets the error handler to make it + // ready to handle a future append error. + else + getErrorHandler()->reset(); + } + + layout->formatAndAppend(out, event); + if(immediateFlush) { + out.flush(); + } +} + +void +FileAppender::open(std::ios::openmode mode) +{ + out.open(LOG4CPLUS_TSTRING_TO_STRING(filename).c_str(), mode); +} + +bool +FileAppender::reopen() +{ + // When append never failed and the file re-open attempt must + // be delayed, set the time when reopen should take place. + if (reopen_time == log4cplus::helpers::Time () && reopenDelay != 0) + reopen_time = log4cplus::helpers::Time::gettimeofday() + + log4cplus::helpers::Time(reopenDelay); + else + { + // Otherwise, check for end of the delay (or absence of delay) to re-open the file. + if (reopen_time <= log4cplus::helpers::Time::gettimeofday() + || reopenDelay == 0) + { + // Close the current file + out.close(); + out.clear(); // reset flags since the C++ standard specified that all the + // flags should remain unchanged on a close + + // Re-open the file. + open(std::ios::app); + + // Reset last fail time. + reopen_time = log4cplus::helpers::Time (); + + // Succeed if no errors are found. + if(out.good()) + return true; + } + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// RollingFileAppender ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +RollingFileAppender::RollingFileAppender(const tstring& filename_, + long maxFileSize_, int maxBackupIndex_, bool immediateFlush_) + : FileAppender(filename_, std::ios::app, immediateFlush_) +{ + init(maxFileSize_, maxBackupIndex_); +} + + +RollingFileAppender::RollingFileAppender(const Properties& properties) + : FileAppender(properties, std::ios::app) +{ + int maxFileSize_ = 10*1024*1024; + int maxBackupIndex_ = 1; + if(properties.exists( LOG4CPLUS_TEXT("MaxFileSize") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("MaxFileSize") ); + tmp = helpers::toUpper(tmp); + maxFileSize_ = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(tmp).c_str()); + if(tmp.find( LOG4CPLUS_TEXT("MB") ) == (tmp.length() - 2)) { + maxFileSize_ *= (1024 * 1024); // convert to megabytes + } + if(tmp.find( LOG4CPLUS_TEXT("KB") ) == (tmp.length() - 2)) { + maxFileSize_ *= 1024; // convert to kilobytes + } + } + + if(properties.exists( LOG4CPLUS_TEXT("MaxBackupIndex") )) { + tstring tmp = properties.getProperty(LOG4CPLUS_TEXT("MaxBackupIndex")); + maxBackupIndex_ = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(tmp).c_str()); + } + + init(maxFileSize_, maxBackupIndex_); +} + + +void +RollingFileAppender::init(long maxFileSize_, int maxBackupIndex_) +{ + if (maxFileSize_ < MINIMUM_ROLLING_LOG_SIZE) + { + tostringstream oss; + oss << LOG4CPLUS_TEXT ("RollingFileAppender: MaxFileSize property") + LOG4CPLUS_TEXT (" value is too small. Resetting to ") + << MINIMUM_ROLLING_LOG_SIZE << "."; + getLogLog ().warn (oss.str ()); + maxFileSize_ = MINIMUM_ROLLING_LOG_SIZE; + } + + this->maxFileSize = maxFileSize_; + this->maxBackupIndex = (std::max)(maxBackupIndex_, 1); +} + + +RollingFileAppender::~RollingFileAppender() +{ + destructorImpl(); +} + + +/////////////////////////////////////////////////////////////////////////////// +// RollingFileAppender protected methods +/////////////////////////////////////////////////////////////////////////////// + +// This method does not need to be locked since it is called by +// doAppend() which performs the locking +void +RollingFileAppender::append(const spi::InternalLoggingEvent& event) +{ + FileAppender::append(event); + + if(out.tellp() > maxFileSize) { + rollover(); + } +} + + +void +RollingFileAppender::rollover() +{ + helpers::LogLog & loglog = getLogLog(); + + // Close the current file + out.close(); + out.clear(); // reset flags since the C++ standard specified that all the + // flags should remain unchanged on a close + + // If maxBackups <= 0, then there is no file renaming to be done. + if (maxBackupIndex > 0) + { + rolloverFiles(filename, maxBackupIndex); + + // Rename fileName to fileName.1 + tstring target = filename + LOG4CPLUS_TEXT(".1"); + + long ret; + +#if defined (WIN32) + // Try to remove the target first. It seems it is not + // possible to rename over existing file. + ret = file_remove (target); +#endif + + loglog.debug ( + LOG4CPLUS_TEXT("Renaming file ") + + filename + + LOG4CPLUS_TEXT(" to ") + + target); + ret = file_rename (filename, target); + loglog_renaming_result (loglog, filename, target, ret); + } + else + { + loglog.debug (filename + LOG4CPLUS_TEXT(" has no backups specified")); + } + + // Open it up again in truncation mode + open(std::ios::out | std::ios::trunc); + loglog_opening_result (loglog, out, filename); +} + + +/////////////////////////////////////////////////////////////////////////////// +// DailyRollingFileAppender ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +DailyRollingFileAppender::DailyRollingFileAppender( + const tstring& filename_, DailyRollingFileSchedule schedule_, + bool immediateFlush_, int maxBackupIndex_) + : FileAppender(filename_, std::ios::app, immediateFlush_) + , maxBackupIndex(maxBackupIndex_) +{ + init(schedule_); +} + + + +DailyRollingFileAppender::DailyRollingFileAppender( + const Properties& properties) + : FileAppender(properties, std::ios::app) + , maxBackupIndex(10) +{ + DailyRollingFileSchedule theSchedule = DAILY; + tstring scheduleStr = properties.getProperty(LOG4CPLUS_TEXT("Schedule")); + scheduleStr = helpers::toUpper(scheduleStr); + + if(scheduleStr == LOG4CPLUS_TEXT("MONTHLY")) + theSchedule = MONTHLY; + else if(scheduleStr == LOG4CPLUS_TEXT("WEEKLY")) + theSchedule = WEEKLY; + else if(scheduleStr == LOG4CPLUS_TEXT("DAILY")) + theSchedule = DAILY; + else if(scheduleStr == LOG4CPLUS_TEXT("TWICE_DAILY")) + theSchedule = TWICE_DAILY; + else if(scheduleStr == LOG4CPLUS_TEXT("HOURLY")) + theSchedule = HOURLY; + else if(scheduleStr == LOG4CPLUS_TEXT("MINUTELY")) + theSchedule = MINUTELY; + else { + getLogLog().warn( LOG4CPLUS_TEXT("DailyRollingFileAppender::ctor()- \"Schedule\" not valid: ") + + properties.getProperty(LOG4CPLUS_TEXT("Schedule"))); + theSchedule = DAILY; + } + + if(properties.exists( LOG4CPLUS_TEXT("MaxBackupIndex") )) { + tstring tmp = properties.getProperty(LOG4CPLUS_TEXT("MaxBackupIndex")); + maxBackupIndex = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(tmp).c_str()); + } + + init(theSchedule); +} + + + +void +DailyRollingFileAppender::init(DailyRollingFileSchedule schedule_) +{ + this->schedule = schedule_; + + Time now = Time::gettimeofday(); + now.usec(0); + struct tm time; + now.localtime(&time); + + time.tm_sec = 0; + switch (schedule) + { + case MONTHLY: + time.tm_mday = 1; + time.tm_hour = 0; + time.tm_min = 0; + break; + + case WEEKLY: + time.tm_mday -= (time.tm_wday % 7); + time.tm_hour = 0; + time.tm_min = 0; + break; + + case DAILY: + time.tm_hour = 0; + time.tm_min = 0; + break; + + case TWICE_DAILY: + if(time.tm_hour >= 12) { + time.tm_hour = 12; + } + else { + time.tm_hour = 0; + } + time.tm_min = 0; + break; + + case HOURLY: + time.tm_min = 0; + break; + + case MINUTELY: + break; + }; + now.setTime(&time); + + scheduledFilename = getFilename(now); + nextRolloverTime = calculateNextRolloverTime(now); +} + + + +DailyRollingFileAppender::~DailyRollingFileAppender() +{ + destructorImpl(); +} + + + + +/////////////////////////////////////////////////////////////////////////////// +// DailyRollingFileAppender public methods +/////////////////////////////////////////////////////////////////////////////// + +void +DailyRollingFileAppender::close() +{ + rollover(); + FileAppender::close(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// DailyRollingFileAppender protected methods +/////////////////////////////////////////////////////////////////////////////// + +// This method does not need to be locked since it is called by +// doAppend() which performs the locking +void +DailyRollingFileAppender::append(const spi::InternalLoggingEvent& event) +{ + if(event.getTimestamp() >= nextRolloverTime) { + rollover(); + } + + FileAppender::append(event); +} + + + +void +DailyRollingFileAppender::rollover() +{ + // Close the current file + out.close(); + out.clear(); // reset flags since the C++ standard specified that all the + // flags should remain unchanged on a close + + // If we've already rolled over this time period, we'll make sure that we + // don't overwrite any of those previous files. + // E.g. if "log.2009-11-07.1" already exists we rename it + // to "log.2009-11-07.2", etc. + rolloverFiles(scheduledFilename, maxBackupIndex); + + // Do not overwriet the newest file either, e.g. if "log.2009-11-07" + // already exists rename it to "log.2009-11-07.1" + tostringstream backup_target_oss; + backup_target_oss << scheduledFilename << LOG4CPLUS_TEXT(".") << 1; + tstring backupTarget = backup_target_oss.str(); + + helpers::LogLog & loglog = getLogLog(); + long ret; + +#if defined (WIN32) + // Try to remove the target first. It seems it is not + // possible to rename over existing file, e.g. "log.2009-11-07.1". + ret = file_remove (backupTarget); +#endif + + // Rename e.g. "log.2009-11-07" to "log.2009-11-07.1". + ret = file_rename (scheduledFilename, backupTarget); + loglog_renaming_result (loglog, scheduledFilename, backupTarget, ret); + +#if defined (WIN32) + // Try to remove the target first. It seems it is not + // possible to rename over existing file, e.g. "log.2009-11-07". + ret = file_remove (scheduledFilename); +#endif + + // Rename filename to scheduledFilename, + // e.g. rename "log" to "log.2009-11-07". + loglog.debug( + LOG4CPLUS_TEXT("Renaming file ") + + filename + + LOG4CPLUS_TEXT(" to ") + + scheduledFilename); + ret = file_rename (filename, scheduledFilename); + loglog_renaming_result (loglog, filename, scheduledFilename, ret); + + // Open a new file, e.g. "log". + open(std::ios::out | std::ios::trunc); + loglog_opening_result (loglog, out, filename); + + // Calculate the next rollover time + log4cplus::helpers::Time now = Time::gettimeofday(); + if (now >= nextRolloverTime) + { + scheduledFilename = getFilename(now); + nextRolloverTime = calculateNextRolloverTime(now); + } +} + + + +Time +DailyRollingFileAppender::calculateNextRolloverTime(const Time& t) const +{ + switch(schedule) + { + case MONTHLY: + { + struct tm nextMonthTime; + t.localtime(&nextMonthTime); + nextMonthTime.tm_mon += 1; + nextMonthTime.tm_isdst = 0; + + Time ret; + if(ret.setTime(&nextMonthTime) == -1) { + getLogLog().error( + LOG4CPLUS_TEXT("DailyRollingFileAppender::calculateNextRolloverTime()-") + LOG4CPLUS_TEXT(" setTime() returned error")); + // Set next rollover to 31 days in future. + ret = (t + Time(2678400)); + } + + return ret; + } + + case WEEKLY: + return (t + Time(7 * 24 * 60 * 60)); + + default: + getLogLog ().error ( + LOG4CPLUS_TEXT ("DailyRollingFileAppender::calculateNextRolloverTime()-") + LOG4CPLUS_TEXT (" invalid schedule value")); + // Fall through. + + case DAILY: + return (t + Time(24 * 60 * 60)); + + case TWICE_DAILY: + return (t + Time(12 * 60 * 60)); + + case HOURLY: + return (t + Time(60 * 60)); + + case MINUTELY: + return (t + Time(60)); + }; +} + + + +tstring +DailyRollingFileAppender::getFilename(const Time& t) const +{ + tchar const * pattern = 0; + switch (schedule) + { + case MONTHLY: + pattern = LOG4CPLUS_TEXT("%Y-%m"); + break; + + case WEEKLY: + pattern = LOG4CPLUS_TEXT("%Y-%W"); + break; + + default: + getLogLog ().error ( + LOG4CPLUS_TEXT ("DailyRollingFileAppender::getFilename()-") + LOG4CPLUS_TEXT (" invalid schedule value")); + // Fall through. + + case DAILY: + pattern = LOG4CPLUS_TEXT("%Y-%m-%d"); + break; + + case TWICE_DAILY: + pattern = LOG4CPLUS_TEXT("%Y-%m-%d-%p"); + break; + + case HOURLY: + pattern = LOG4CPLUS_TEXT("%Y-%m-%d-%H"); + break; + + case MINUTELY: + pattern = LOG4CPLUS_TEXT("%Y-%m-%d-%H-%M"); + break; + }; + + tstring result (filename); + result += LOG4CPLUS_TEXT("."); + result += t.getFormattedTime(pattern, false); + return result; +} + +} // namespace log4cplus diff --git a/libs/log4cplus/src/filter.cxx b/libs/log4cplus/src/filter.cxx new file mode 100644 index 0000000..1adbca4 --- /dev/null +++ b/libs/log4cplus/src/filter.cxx @@ -0,0 +1,256 @@ +// Module: Log4CPLUS +// File: filter.cxx +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include + +using namespace log4cplus; +using namespace log4cplus::spi; +using namespace log4cplus::helpers; + + +/////////////////////////////////////////////////////////////////////////////// +// global methods +/////////////////////////////////////////////////////////////////////////////// + +FilterResult +log4cplus::spi::checkFilter(const Filter* filter, + const InternalLoggingEvent& event) +{ + const Filter* currentFilter = filter; + while(currentFilter) { + FilterResult result = currentFilter->decide(event); + if(result != NEUTRAL) { + return result; + } + + currentFilter = currentFilter->next.get(); + } + + return ACCEPT; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Filter implementation +/////////////////////////////////////////////////////////////////////////////// + +Filter::Filter() +{ +} + + +Filter::~Filter() +{ +} + + +void +Filter::appendFilter(FilterPtr filter) +{ + if(next.get() == 0) { + next = filter; + } + else { + next->appendFilter(filter); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// DenyAllFilter implementation +/////////////////////////////////////////////////////////////////////////////// + +DenyAllFilter::DenyAllFilter () +{ } + + +DenyAllFilter::DenyAllFilter (const log4cplus::helpers::Properties&) +{ } + + +FilterResult +DenyAllFilter::decide(const InternalLoggingEvent&) const +{ + return DENY; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// LogLevelMatchFilter implementation +/////////////////////////////////////////////////////////////////////////////// + +LogLevelMatchFilter::LogLevelMatchFilter() +{ + init(); +} + + + +LogLevelMatchFilter::LogLevelMatchFilter(const Properties& properties) +{ + init(); + + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("AcceptOnMatch") ); + acceptOnMatch = (toLower(tmp) == LOG4CPLUS_TEXT("true")); + + tmp = properties.getProperty( LOG4CPLUS_TEXT("LogLevelToMatch") ); + logLevelToMatch = getLogLevelManager().fromString(tmp); +} + + +void +LogLevelMatchFilter::init() +{ + acceptOnMatch = true; + logLevelToMatch = NOT_SET_LOG_LEVEL; +} + + +FilterResult +LogLevelMatchFilter::decide(const InternalLoggingEvent& event) const +{ + if(logLevelToMatch == NOT_SET_LOG_LEVEL) { + return NEUTRAL; + } + + bool matchOccured = (logLevelToMatch == event.getLogLevel()); + + if(matchOccured) { + return (acceptOnMatch ? ACCEPT : DENY); + } + else { + return NEUTRAL; + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// LogLevelRangeFilter implementation +/////////////////////////////////////////////////////////////////////////////// + +LogLevelRangeFilter::LogLevelRangeFilter() +{ + init(); +} + + + +LogLevelRangeFilter::LogLevelRangeFilter(const Properties& properties) +{ + init(); + + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("AcceptOnMatch") ); + acceptOnMatch = (toLower(tmp) == LOG4CPLUS_TEXT("true")); + + tmp = properties.getProperty( LOG4CPLUS_TEXT("LogLevelMin") ); + logLevelMin = getLogLevelManager().fromString(tmp); + + tmp = properties.getProperty( LOG4CPLUS_TEXT("LogLevelMax") ); + logLevelMax = getLogLevelManager().fromString(tmp); +} + + +void +LogLevelRangeFilter::init() +{ + acceptOnMatch = true; + logLevelMin = NOT_SET_LOG_LEVEL; + logLevelMax = NOT_SET_LOG_LEVEL; +} + + +FilterResult +LogLevelRangeFilter::decide(const InternalLoggingEvent& event) const +{ + if((logLevelMin != NOT_SET_LOG_LEVEL) && (event.getLogLevel() < logLevelMin)) { + // priority of event is less than minimum + return DENY; + } + + if((logLevelMax != NOT_SET_LOG_LEVEL) && (event.getLogLevel() > logLevelMax)) { + // priority of event is greater than maximum + return DENY; + } + + if(acceptOnMatch) { + // this filter set up to bypass later filters and always return + // accept if priority in range + return ACCEPT; + } + else { + // event is ok for this filter; allow later filters to have a look... + return NEUTRAL; + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// StringMatchFilter implementation +/////////////////////////////////////////////////////////////////////////////// + +StringMatchFilter::StringMatchFilter() +{ + init(); +} + + + +StringMatchFilter::StringMatchFilter(const Properties& properties) +{ + init(); + + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("AcceptOnMatch") ); + acceptOnMatch = (toLower(tmp) == LOG4CPLUS_TEXT("true")); + + stringToMatch = properties.getProperty( LOG4CPLUS_TEXT("StringToMatch") ); +} + + +void +StringMatchFilter::init() +{ + acceptOnMatch = true; +} + + +FilterResult +StringMatchFilter::decide(const InternalLoggingEvent& event) const +{ + const tstring& message = event.getMessage(); + + if(stringToMatch.empty () || message.empty ()) { + return NEUTRAL; + } + + if(message.find(stringToMatch) == tstring::npos) { + return NEUTRAL; + } + else { // we've got a match + return (acceptOnMatch ? ACCEPT : DENY); + } +} + diff --git a/libs/log4cplus/src/global-init.cxx b/libs/log4cplus/src/global-init.cxx new file mode 100644 index 0000000..426b301 --- /dev/null +++ b/libs/log4cplus/src/global-init.cxx @@ -0,0 +1,101 @@ +// Module: Log4CPLUS +// File: global-init.cxx +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include + + +// Forward Declarations +namespace log4cplus +{ + + +//! Defined here, used by initializeLayout(). +helpers::Time TTCCLayout_time_base; + + +void initializeFactoryRegistry(); +void initializeLayout (); + + +void initializeLog4cplus() +{ + static bool initialized = false; + if (initialized) + return; + + helpers::LogLog::getLogLog(); + getLogLevelManager (); + getNDC(); + Logger::getRoot(); + initializeFactoryRegistry(); + initializeLayout (); + + initialized = true; +} + + +} // namespace log4cplus + + +#if defined (_WIN32) && defined (LOG4CPLUS_BUILD_DLL) + +BOOL WINAPI DllMain(LOG4CPLUS_DLLMAIN_HINSTANCE hinstDLL, // handle to DLL module + DWORD fdwReason, // reason for calling function + LPVOID lpReserved ) // reserved +{ + // Perform actions based on the reason for calling. + switch( fdwReason ) + { + case DLL_PROCESS_ATTACH: + log4cplus::initializeLog4cplus(); + break; + + case DLL_THREAD_ATTACH: + // Do thread-specific initialization. + break; + + case DLL_THREAD_DETACH: + // Do thread-specific cleanup. + break; + + case DLL_PROCESS_DETACH: + // Perform any necessary cleanup. + break; + } + + return TRUE; // Successful DLL_PROCESS_ATTACH. +} + +#else + +namespace { + + class _static_log4cplus_initializer { + public: + _static_log4cplus_initializer() { + log4cplus::initializeLog4cplus(); + } + } static initializer; +} + +#endif diff --git a/libs/log4cplus/src/hierarchy.cxx b/libs/log4cplus/src/hierarchy.cxx new file mode 100644 index 0000000..8ad0653 --- /dev/null +++ b/libs/log4cplus/src/hierarchy.cxx @@ -0,0 +1,352 @@ +// Module: Log4CPLUS +// File: hierarchy.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include + +using namespace log4cplus; +using namespace log4cplus::helpers; + + +////////////////////////////////////////////////////////////////////////////// +// File "Local" methods +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + +static +bool startsWith(tstring const & teststr, tstring const & substr) +{ + bool val = false; + tstring::size_type const len = substr.length(); + if (teststr.length() > len) + val = teststr.compare (0, len, substr) == 0; + + return val; +} + +} + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::Hierarchy static declarations +////////////////////////////////////////////////////////////////////////////// + +const LogLevel log4cplus::Hierarchy::DISABLE_OFF = -1; +const LogLevel log4cplus::Hierarchy::DISABLE_OVERRIDE = -2; + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::Hierarchy ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +Hierarchy::Hierarchy() + : hashtable_mutex(LOG4CPLUS_MUTEX_CREATE), + defaultFactory(new DefaultLoggerFactory()), + root(NULL), + disableValue(DISABLE_OFF), // Don't disable any LogLevel level by default. + emittedNoAppenderWarning(false), + emittedNoResourceBundleWarning(false) +{ + root = Logger( new spi::RootLogger(*this, DEBUG_LOG_LEVEL) ); +} + + +Hierarchy::~Hierarchy() +{ + shutdown(); + LOG4CPLUS_MUTEX_FREE( hashtable_mutex ); +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::Hierarchy public methods +////////////////////////////////////////////////////////////////////////////// + +void +Hierarchy::clear() +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( hashtable_mutex ) + provisionNodes.erase(provisionNodes.begin(), provisionNodes.end()); + loggerPtrs.erase(loggerPtrs.begin(), loggerPtrs.end()); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +bool +Hierarchy::exists(const log4cplus::tstring& name) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( hashtable_mutex ) + LoggerMap::iterator it = loggerPtrs.find(name); + return it != loggerPtrs.end(); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +void +Hierarchy::disable(const log4cplus::tstring& loglevelStr) +{ + if(disableValue != DISABLE_OVERRIDE) { + disableValue = getLogLevelManager().fromString(loglevelStr); + } +} + + +void +Hierarchy::disable(LogLevel ll) +{ + if(disableValue != DISABLE_OVERRIDE) { + disableValue = ll; + } +} + + +void +Hierarchy::disableAll() +{ + disable(FATAL_LOG_LEVEL); +} + + +void +Hierarchy::disableDebug() +{ + disable(DEBUG_LOG_LEVEL); +} + + +void +Hierarchy::disableInfo() +{ + disable(INFO_LOG_LEVEL); +} + + +void +Hierarchy::enableAll() +{ + disableValue = DISABLE_OFF; +} + + +Logger +Hierarchy::getInstance(const log4cplus::tstring& name) +{ + return getInstance(name, *defaultFactory); +} + + +Logger +Hierarchy::getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( hashtable_mutex ) + return getInstanceImpl(name, factory); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +LoggerList +Hierarchy::getCurrentLoggers() +{ + LoggerList ret; + + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( hashtable_mutex ) + initializeLoggerList(ret); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; + + return ret; +} + + +bool +Hierarchy::isDisabled(int level) +{ + return disableValue >= level; +} + + +Logger +Hierarchy::getRoot() const +{ + return root; +} + + +void +Hierarchy::resetConfiguration() +{ + getRoot().setLogLevel(DEBUG_LOG_LEVEL); + disableValue = DISABLE_OFF; + + shutdown(); + + LoggerList loggers = getCurrentLoggers(); + LoggerList::iterator it = loggers.begin(); + while(it != loggers.end()) { + (*it).setLogLevel(NOT_SET_LOG_LEVEL); + (*it).setAdditivity(true); + ++it; + } + +} + + +void +Hierarchy::setLoggerFactory(std::auto_ptr factory) +{ + defaultFactory = factory; +} + + +void +Hierarchy::shutdown() +{ + LoggerList loggers = getCurrentLoggers(); + + // begin by closing nested appenders + // then, remove all appenders + root.closeNestedAppenders(); + root.removeAllAppenders(); + + // repeat + LoggerList::iterator it = loggers.begin(); + while(it != loggers.end()) { + (*it).closeNestedAppenders(); + (*it).removeAllAppenders(); + ++it; + } +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::Hierarchy private methods +////////////////////////////////////////////////////////////////////////////// + +Logger +Hierarchy::getInstanceImpl(const log4cplus::tstring& name, spi::LoggerFactory& factory) +{ + LoggerMap::iterator it = loggerPtrs.find(name); + if(it != loggerPtrs.end()) { + return (*it).second; + } + else { + // Need to create a new logger + Logger logger = factory.makeNewLoggerInstance(name, *this); + bool inserted = loggerPtrs.insert(std::make_pair(name, logger)).second; + if(!inserted) { + getLogLog().error(LOG4CPLUS_TEXT("Hierarchy::getInstanceImpl()- Insert failed")); + throw std::runtime_error("Hierarchy::getInstanceImpl()- Insert failed"); + } + + ProvisionNodeMap::iterator it2 = provisionNodes.find(name); + if(it2 != provisionNodes.end()) { + updateChildren(it2->second, logger); + bool deleted = (provisionNodes.erase(name) > 0); + if(!deleted) { + getLogLog().error(LOG4CPLUS_TEXT("Hierarchy::getInstanceImpl()- Delete failed")); + throw std::runtime_error("Hierarchy::getInstanceImpl()- Delete failed"); + } + } + updateParents(logger); + + return logger; + } +} + + +void +Hierarchy::initializeLoggerList(LoggerList& list) const +{ + for(LoggerMap::const_iterator it=loggerPtrs.begin(); + it!= loggerPtrs.end(); + ++it) + { + list.push_back((*it).second); + } +} + + +void +Hierarchy::updateParents(Logger logger) +{ + log4cplus::tstring name = logger.getName(); + size_t length = name.length(); + bool parentFound = false; + + // if name = "w.x.y.z", loop thourgh "w.x.y", "w.x" and "w", but not "w.x.y.z" + for(size_t i=name.find_last_of(LOG4CPLUS_TEXT('.'), length-1); + i != log4cplus::tstring::npos && i > 0; + i = name.find_last_of(LOG4CPLUS_TEXT('.'), i-1)) + { + log4cplus::tstring substr = name.substr(0, i); + + LoggerMap::iterator it = loggerPtrs.find(substr); + if(it != loggerPtrs.end()) { + parentFound = true; + logger.value->parent = it->second.value; + break; // no need to update the ancestors of the closest ancestor + } + else { + ProvisionNodeMap::iterator it2 = provisionNodes.find(substr); + if(it2 != provisionNodes.end()) { + it2->second.push_back(logger); + } + else { + ProvisionNode node; + node.push_back(logger); + std::pair tmp = + provisionNodes.insert(std::make_pair(substr, node)); + //bool inserted = provisionNodes.insert(std::make_pair(substr, node)).second; + if(!tmp.second) { + getLogLog().error(LOG4CPLUS_TEXT("Hierarchy::updateParents()- Insert failed")); + throw std::runtime_error("Hierarchy::updateParents()- Insert failed"); + } + } + } // end if Logger found + } // end for loop + + if(!parentFound) { + logger.value->parent = root.value; + } +} + + +void +Hierarchy::updateChildren(ProvisionNode& pn, Logger logger) +{ + + for(ProvisionNode::iterator it=pn.begin(); it!=pn.end(); ++it) { + Logger& c = *it; + // Unless this child already points to a correct (lower) parent, + // make logger.parent point to c.parent and c.parent to logger. + if( !startsWith(c.value->parent->getName(), logger.getName()) ) { + logger.value->parent = c.value->parent; + c.value->parent = logger.value; + } + } +} + diff --git a/libs/log4cplus/src/hierarchylocker.cxx b/libs/log4cplus/src/hierarchylocker.cxx new file mode 100644 index 0000000..cf0b98b --- /dev/null +++ b/libs/log4cplus/src/hierarchylocker.cxx @@ -0,0 +1,124 @@ +// Module: Log4CPLUS +// File: hierarchylocker.cxx +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 +#include +#include + + +using namespace log4cplus; +using namespace log4cplus::helpers; + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::HierarchyLocker ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +HierarchyLocker::HierarchyLocker(Hierarchy& _h) +: h(_h), + hierarchyLocker(h.hashtable_mutex), + loggerList() +{ + // Get a copy of all of the Hierarchy's Loggers (except the Root Logger) + h.initializeLoggerList(loggerList); + + // Lock all of the Hierarchy's Loggers' mutexs + try { + for(LoggerList::iterator it=loggerList.begin(); it!=loggerList.end(); ++it) { + LOG4CPLUS_MUTEX_LOCK( (*it).value->appender_list_mutex ) ; + } + } + catch(...) { + h.getLogLog().error(LOG4CPLUS_TEXT("HierarchyLocker::ctor()- An error occurred while locking")); + // TODO --> We need to unlock any Logger mutex that we were able to lock + throw; + } +} + + +HierarchyLocker::~HierarchyLocker() +{ + try { + for(LoggerList::iterator it=loggerList.begin(); it!=loggerList.end(); ++it) { + LOG4CPLUS_MUTEX_UNLOCK( (*it).value->appender_list_mutex ) ; + } + } + catch(...) { + h.getLogLog().error(LOG4CPLUS_TEXT("HierarchyLocker::dtor()- An error occurred while unlocking")); + throw; + } +} + +void +HierarchyLocker::resetConfiguration() +{ + Logger root = h.getRoot(); + h.disable(log4cplus::Hierarchy::DISABLE_OFF); + + // begin by closing nested appenders + // then, remove all appenders + root.setLogLevel(DEBUG_LOG_LEVEL); + root.closeNestedAppenders(); + root.removeAllAppenders(); + + // repeat + for(LoggerList::iterator it=loggerList.begin(); it!=loggerList.end(); ++it) { + LOG4CPLUS_MUTEX_UNLOCK( (*it).value->appender_list_mutex ) ; + (*it).closeNestedAppenders(); + (*it).removeAllAppenders(); + LOG4CPLUS_MUTEX_LOCK( (*it).value->appender_list_mutex ) ; + (*it).setLogLevel(NOT_SET_LOG_LEVEL); + (*it).setAdditivity(true); + } +} + + +Logger +HierarchyLocker::getInstance(const log4cplus::tstring& name) +{ + return h.getInstanceImpl(name, *h.getLoggerFactory()); +} + + +Logger +HierarchyLocker::getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory) +{ + return h.getInstanceImpl(name, factory); +} + + +void +HierarchyLocker::addAppender(Logger& logger, log4cplus::SharedAppenderPtr& appender) +{ + for(LoggerList::iterator it=loggerList.begin(); it!=loggerList.end(); ++it) { + if((*it).value == logger.value) { + LOG4CPLUS_MUTEX_UNLOCK( logger.value->appender_list_mutex ); + logger.addAppender(appender); + LOG4CPLUS_MUTEX_LOCK( logger.value->appender_list_mutex ); + return; + } + } + + // I don't have this Logger locked + logger.addAppender(appender); +} + + diff --git a/libs/log4cplus/src/layout.cxx b/libs/log4cplus/src/layout.cxx new file mode 100644 index 0000000..5167aba --- /dev/null +++ b/libs/log4cplus/src/layout.cxx @@ -0,0 +1,127 @@ +// Module: Log4CPLUS +// File: layout.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include +#include + + +namespace log4cplus +{ + + +extern helpers::Time TTCCLayout_time_base; + + +void +initializeLayout () +{ + TTCCLayout_time_base = helpers::Time::gettimeofday (); +} + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::SimpleLayout public methods +/////////////////////////////////////////////////////////////////////////////// + +void +SimpleLayout::formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event) +{ + output << llmCache.toString(event.getLogLevel()) + << LOG4CPLUS_TEXT(" - ") + << event.getMessage() + << LOG4CPLUS_TEXT("\n"); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::TTCCLayout ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +TTCCLayout::TTCCLayout(bool use_gmtime_) +: dateFormat(), + use_gmtime(use_gmtime_) +{ +} + + +TTCCLayout::TTCCLayout(const log4cplus::helpers::Properties& properties) +: Layout(properties), + dateFormat(), + use_gmtime(false) +{ + if(properties.exists( LOG4CPLUS_TEXT("DateFormat") )) { + dateFormat = properties.getProperty( LOG4CPLUS_TEXT("DateFormat") ); + } + + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("Use_gmtime") ); + use_gmtime = (helpers::toLower(tmp) == LOG4CPLUS_TEXT("true")); +} + + +TTCCLayout::~TTCCLayout() +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::TTCCLayout public methods +/////////////////////////////////////////////////////////////////////////////// + +void +TTCCLayout::formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event) +{ + if (dateFormat.empty ()) + { + helpers::Time const rel_time = event.getTimestamp () - TTCCLayout_time_base; + tchar const old_fill = output.fill (); + time_t const sec = rel_time.sec (); + + if (sec != 0) + output << sec << std::setfill (LOG4CPLUS_TEXT ('0')) + << std::setw (3); + + output << rel_time.usec () / 1000; + output.fill (old_fill); + } + else + output << event.getTimestamp().getFormattedTime(dateFormat, use_gmtime); + + output << LOG4CPLUS_TEXT(" [") + << event.getThread() + << LOG4CPLUS_TEXT("] ") + << llmCache.toString(event.getLogLevel()) + << LOG4CPLUS_TEXT(" ") + << event.getLoggerName() + << LOG4CPLUS_TEXT(" <") + << event.getNDC() + << LOG4CPLUS_TEXT("> - ") + << event.getMessage() + << LOG4CPLUS_TEXT("\n"); +} + + +} // namespace log4cplus diff --git a/libs/log4cplus/src/logger.cxx b/libs/log4cplus/src/logger.cxx new file mode 100644 index 0000000..ed8ba71 --- /dev/null +++ b/libs/log4cplus/src/logger.cxx @@ -0,0 +1,298 @@ +// Module: Log4CPLUS +// File: logger.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include +#include + + +namespace log4cplus +{ + + +Logger +DefaultLoggerFactory::makeNewLoggerInstance (const tstring & name, + Hierarchy& h) +{ + return Logger (new spi::LoggerImpl (name, h)); +} + + +////////////////////////////////////////////////////////////////////////////// +// static Logger Methods +////////////////////////////////////////////////////////////////////////////// +// +Hierarchy & +Logger::getDefaultHierarchy () +{ + static Hierarchy defaultHierarchy; + + return defaultHierarchy; +} + + +bool +Logger::exists (const tstring & name) +{ + return getDefaultHierarchy().exists(name); +} + + +LoggerList +Logger::getCurrentLoggers () +{ + return getDefaultHierarchy ().getCurrentLoggers (); +} + + +Logger +Logger::getInstance (const tstring& name) +{ + return getDefaultHierarchy().getInstance(name); +} + + +Logger +Logger::getInstance (const tstring& name, + spi::LoggerFactory& factory) +{ + return getDefaultHierarchy().getInstance(name, factory); +} + + +Logger +Logger::getRoot () +{ + return getDefaultHierarchy ().getRoot (); +} + + +void +Logger::shutdown () +{ + getDefaultHierarchy ().shutdown (); +} + + + +////////////////////////////////////////////////////////////////////////////// +// Logger ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +Logger::Logger () + : value (0) +{ } + + +Logger::Logger (spi::LoggerImpl * ptr) + : value (ptr) +{ + if (value) + value->addReference (); +} + + +Logger::Logger (const Logger& rhs) + : spi::AppenderAttachable (rhs) + , value (rhs.value) +{ + if (value) + value->addReference (); +} + + +Logger & +Logger::operator = (const Logger& rhs) +{ + Logger (rhs).swap (*this); + return *this; +} + + +Logger::~Logger () +{ + if (value) + value->removeReference (); +} + + +////////////////////////////////////////////////////////////////////////////// +// Logger Methods +////////////////////////////////////////////////////////////////////////////// + +void +Logger::swap (Logger & other) +{ + std::swap (value, other.value); +} + + +Logger +Logger::getParent () const +{ + if (value->parent) + return Logger (value->parent.get ()); + else + { + value->getLogLog().error(LOG4CPLUS_TEXT("********* This logger has no parent: " + getName())); + return *this; + } +} + + +void +Logger::addAppender (SharedAppenderPtr newAppender) +{ + value->addAppender(newAppender); +} + + +SharedAppenderPtrList +Logger::getAllAppenders () +{ + return value->getAllAppenders(); +} + + +SharedAppenderPtr +Logger::getAppender (const tstring& name) +{ + return value->getAppender (name); +} + + +void +Logger::removeAllAppenders () +{ + value->removeAllAppenders (); +} + + +void +Logger::removeAppender (SharedAppenderPtr appender) +{ + value->removeAppender(appender); +} + + +void +Logger::removeAppender (const tstring& name) +{ + value->removeAppender (name); +} + + +void +Logger::assertion (bool assertionVal, const tstring& msg) const +{ + if (! assertionVal) + log (FATAL_LOG_LEVEL, msg); +} + + +void +Logger::closeNestedAppenders () const +{ + value->closeNestedAppenders (); +} + + +bool +Logger::isEnabledFor (LogLevel ll) const +{ + return value->isEnabledFor (ll); +} + + +void +Logger::log (LogLevel ll, const tstring& message, const char* file, + int line) const +{ + value->log (ll, message, file, line); +} + + +void +Logger::forcedLog (LogLevel ll, const tstring& message, + const char* file, int line) const +{ + value->forcedLog (ll, message, file, line); +} + + +void +Logger::callAppenders (const spi::InternalLoggingEvent& event) const +{ + value->callAppenders (event); +} + + +LogLevel +Logger::getChainedLogLevel () const +{ + return value->getChainedLogLevel (); +} + + +LogLevel +Logger::getLogLevel() const +{ + return value->getLogLevel (); +} + + +void +Logger::setLogLevel (LogLevel ll) +{ + value->setLogLevel (ll); +} + + +Hierarchy & +Logger::getHierarchy () const +{ + return value->getHierarchy (); +} + + +tstring +Logger::getName () const +{ + return value->getName (); +} + + +bool +Logger::getAdditivity () const +{ + return value->getAdditivity (); +} + + +void +Logger::setAdditivity (bool additive) +{ + value->setAdditivity (additive); +} + + +} // namespace log4cplus diff --git a/libs/log4cplus/src/loggerimpl.cxx b/libs/log4cplus/src/loggerimpl.cxx new file mode 100644 index 0000000..22f2145 --- /dev/null +++ b/libs/log4cplus/src/loggerimpl.cxx @@ -0,0 +1,158 @@ +// Module: Log4CPLUS +// File: loggerimpl.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include +#include + +using namespace log4cplus; +using namespace log4cplus::helpers; +using namespace log4cplus::spi; + + + +////////////////////////////////////////////////////////////////////////////// +// Logger Constructors and Destructor +////////////////////////////////////////////////////////////////////////////// +LoggerImpl::LoggerImpl(const log4cplus::tstring& name_, Hierarchy& h) + : name(name_), + ll(NOT_SET_LOG_LEVEL), + parent(NULL), + additive(true), + hierarchy(h) +{ +} + + +LoggerImpl::~LoggerImpl() +{ +} + + +////////////////////////////////////////////////////////////////////////////// +// Logger Methods +////////////////////////////////////////////////////////////////////////////// + +void +LoggerImpl::callAppenders(const InternalLoggingEvent& event) +{ + int writes = 0; + for(const LoggerImpl* c = this; c != NULL; c=c->parent.get()) { + writes += c->appendLoopOnAppenders(event); + if(!c->additive) { + break; + } + } + + // No appenders in hierarchy, warn user only once. + if(!hierarchy.emittedNoAppenderWarning && writes == 0) { + getLogLog().error( LOG4CPLUS_TEXT("No appenders could be found for logger (") + + getName() + + LOG4CPLUS_TEXT(").")); + getLogLog().error(LOG4CPLUS_TEXT("Please initialize the log4cplus system properly.")); + hierarchy.emittedNoAppenderWarning = true; + } +} + + +void +LoggerImpl::closeNestedAppenders() +{ + SharedAppenderPtrList appenders = getAllAppenders(); + for(SharedAppenderPtrList::iterator it=appenders.begin(); it!=appenders.end(); ++it) + { + (*it)->close(); + } +} + + +bool +LoggerImpl::isEnabledFor(LogLevel ll_) const +{ + if(hierarchy.disableValue >= ll_) { + return false; + } + return ll_ >= getChainedLogLevel(); +} + + +void +LoggerImpl::log(LogLevel ll_, + const log4cplus::tstring& message, + const char* file, + int line) +{ + if(isEnabledFor(ll_)) { + forcedLog(ll_, message, file, line); + } +} + + + +LogLevel +LoggerImpl::getChainedLogLevel() const +{ + for(const LoggerImpl *c=this; c != NULL; c=c->parent.get()) { + if(c->ll != NOT_SET_LOG_LEVEL) { + return c->ll; + } + } + + getLogLog().error( LOG4CPLUS_TEXT("LoggerImpl::getChainedLogLevel()- No valid LogLevel found") ); + throw std::runtime_error("No valid LogLevel found"); +} + + +Hierarchy& +LoggerImpl::getHierarchy() const +{ + return hierarchy; +} + + +bool +LoggerImpl::getAdditivity() const +{ + return additive; +} + + +void +LoggerImpl::setAdditivity(bool additive_) +{ + this->additive = additive_; +} + + +void +LoggerImpl::forcedLog(LogLevel ll_, + const log4cplus::tstring& message, + const char* file, + int line) +{ + callAppenders(spi::InternalLoggingEvent(this->getName(), ll_, message, file, line)); +} + + + diff --git a/libs/log4cplus/src/loggingevent.cxx b/libs/log4cplus/src/loggingevent.cxx new file mode 100644 index 0000000..5c44a52 --- /dev/null +++ b/libs/log4cplus/src/loggingevent.cxx @@ -0,0 +1,100 @@ +// Module: Log4CPLUS +// File: loggingevent.cxx +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 + + +using namespace log4cplus; +using namespace log4cplus::spi; + + +#define LOG4CPLUS_DEFAULT_TYPE 1 + + +/////////////////////////////////////////////////////////////////////////////// +// InternalLoggingEvent dtor +/////////////////////////////////////////////////////////////////////////////// + +InternalLoggingEvent::~InternalLoggingEvent() +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +// InternalLoggingEvent static methods +/////////////////////////////////////////////////////////////////////////////// + +unsigned int +InternalLoggingEvent::getDefaultType() +{ + return LOG4CPLUS_DEFAULT_TYPE; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// InternalLoggingEvent implementation +/////////////////////////////////////////////////////////////////////////////// + +const log4cplus::tstring& +InternalLoggingEvent::getMessage() const +{ + return message; +} + + +unsigned int +InternalLoggingEvent::getType() const +{ + return LOG4CPLUS_DEFAULT_TYPE; +} + + + +std::auto_ptr +InternalLoggingEvent::clone() const +{ + std::auto_ptr tmp(new InternalLoggingEvent(*this)); + return tmp; +} + + + +log4cplus::spi::InternalLoggingEvent& +InternalLoggingEvent::operator=(const log4cplus::spi::InternalLoggingEvent& rhs) +{ + if(this == &rhs) return *this; + + message = rhs.message; + loggerName = rhs.loggerName; + ll = rhs.ll; + ndc = rhs.getNDC(); + thread = rhs.getThread(); + timestamp = rhs.timestamp; + file = rhs.file; + line = rhs.line; + threadCached = true; + ndcCached = true; + + return *this; +} + + diff --git a/libs/log4cplus/src/loglevel.cxx b/libs/log4cplus/src/loglevel.cxx new file mode 100644 index 0000000..02d5d56 --- /dev/null +++ b/libs/log4cplus/src/loglevel.cxx @@ -0,0 +1,221 @@ +// Module: Log4CPLUS +// File: loglevel.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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 +#include +#include +#include + +using namespace log4cplus; +using namespace log4cplus::helpers; + +#define _ALL_STRING LOG4CPLUS_TEXT("ALL") +#define _TRACE_STRING LOG4CPLUS_TEXT("TRACE") +#define _DEBUG_STRING LOG4CPLUS_TEXT("DEBUG") +#define _INFO_STRING LOG4CPLUS_TEXT("INFO") +#define _WARN_STRING LOG4CPLUS_TEXT("WARN") +#define _ERROR_STRING LOG4CPLUS_TEXT("ERROR") +#define _FATAL_STRING LOG4CPLUS_TEXT("FATAL") +#define _OFF_STRING LOG4CPLUS_TEXT("OFF") +#define _NOTSET_STRING LOG4CPLUS_TEXT("NOTSET") +#define _UNKNOWN_STRING LOG4CPLUS_TEXT("UNKNOWN") + +#define GET_TO_STRING_NODE static_cast(this->toStringMethods) +#define GET_FROM_STRING_NODE static_cast(this->fromStringMethods) + + + +////////////////////////////////////////////////////////////////////////////// +// file LOCAL definitions +////////////////////////////////////////////////////////////////////////////// + +namespace { + class ToStringNode { + public: + ToStringNode(LogLevelToStringMethod m) : method(m), next(0) {} + + LogLevelToStringMethod method; + ToStringNode* next; + }; + + + class FromStringNode { + public: + FromStringNode(StringToLogLevelMethod m) : method(m), next(0) {} + + StringToLogLevelMethod method; + FromStringNode* next; + }; + + + static + log4cplus::tstring + defaultLogLevelToStringMethod(LogLevel ll) { + switch(ll) { + case OFF_LOG_LEVEL: return _OFF_STRING; + case FATAL_LOG_LEVEL: return _FATAL_STRING; + case ERROR_LOG_LEVEL: return _ERROR_STRING; + case WARN_LOG_LEVEL: return _WARN_STRING; + case INFO_LOG_LEVEL: return _INFO_STRING; + case DEBUG_LOG_LEVEL: return _DEBUG_STRING; + case TRACE_LOG_LEVEL: return _TRACE_STRING; + //case ALL_LOG_LEVEL: return _ALL_STRING; + case NOT_SET_LOG_LEVEL: return _NOTSET_STRING; + }; + + return tstring(); + } + + + static + LogLevel + defaultStringToLogLevelMethod(const log4cplus::tstring& arg) { + log4cplus::tstring s = log4cplus::helpers::toUpper(arg); + + if(s == _ALL_STRING) return ALL_LOG_LEVEL; + if(s == _TRACE_STRING) return TRACE_LOG_LEVEL; + if(s == _DEBUG_STRING) return DEBUG_LOG_LEVEL; + if(s == _INFO_STRING) return INFO_LOG_LEVEL; + if(s == _WARN_STRING) return WARN_LOG_LEVEL; + if(s == _ERROR_STRING) return ERROR_LOG_LEVEL; + if(s == _FATAL_STRING) return FATAL_LOG_LEVEL; + if(s == _OFF_STRING) return OFF_LOG_LEVEL; + + return NOT_SET_LOG_LEVEL; + } + +} + + + +////////////////////////////////////////////////////////////////////////////// +// public static methods +////////////////////////////////////////////////////////////////////////////// + +LogLevelManager& +log4cplus::getLogLevelManager() +{ + static LogLevelManager singleton; + return singleton; +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::LogLevelManager ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +LogLevelManager::LogLevelManager() +: toStringMethods(new ToStringNode(defaultLogLevelToStringMethod)), + fromStringMethods(new FromStringNode(defaultStringToLogLevelMethod)) +{ +} + + + +LogLevelManager::~LogLevelManager() +{ + ToStringNode* toStringTmp = GET_TO_STRING_NODE; + while(toStringTmp) { + ToStringNode* tmp = toStringTmp; + toStringTmp = toStringTmp->next; + delete tmp; + } + + FromStringNode* fromStringTmp = GET_FROM_STRING_NODE; + while(fromStringTmp) { + FromStringNode* tmp = fromStringTmp; + fromStringTmp = fromStringTmp->next; + delete tmp; + } +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::LogLevelManager public methods +////////////////////////////////////////////////////////////////////////////// + +log4cplus::tstring +LogLevelManager::toString(LogLevel ll) const +{ + ToStringNode* toStringTmp = GET_TO_STRING_NODE; + while(toStringTmp) { + tstring ret = toStringTmp->method(ll); + if(! ret.empty ()) { + return ret; + } + toStringTmp = toStringTmp->next; + } + + return _UNKNOWN_STRING; +} + + + +LogLevel +LogLevelManager::fromString(const log4cplus::tstring& s) const +{ + FromStringNode* fromStringTmp = GET_FROM_STRING_NODE; + while(fromStringTmp) { + LogLevel ret = fromStringTmp->method(s); + if(ret != NOT_SET_LOG_LEVEL) { + return ret; + } + fromStringTmp = fromStringTmp->next; + } + + return NOT_SET_LOG_LEVEL; +} + + + +void +LogLevelManager::pushToStringMethod(LogLevelToStringMethod newToString) +{ + ToStringNode* toStringTmp = GET_TO_STRING_NODE; + while(1) { + if(toStringTmp->next) { + toStringTmp = toStringTmp->next; + } + else { + toStringTmp->next = new ToStringNode(newToString); + break; + } + } +} + + + +void +LogLevelManager::pushFromStringMethod(StringToLogLevelMethod newFromString) +{ + FromStringNode* fromStringTmp = GET_FROM_STRING_NODE; + while(1) { + if(fromStringTmp->next) { + fromStringTmp = fromStringTmp->next; + } + else { + fromStringTmp->next = new FromStringNode(newFromString); + break; + } + } +} + diff --git a/libs/log4cplus/src/loglog.cxx b/libs/log4cplus/src/loglog.cxx new file mode 100644 index 0000000..538d132 --- /dev/null +++ b/libs/log4cplus/src/loglog.cxx @@ -0,0 +1,122 @@ +// Module: Log4CPLUS +// File: loglog.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include + +using namespace std; +using namespace log4cplus; +using namespace log4cplus::helpers; + + +namespace +{ + +static tchar const PREFIX[] = LOG4CPLUS_TEXT("log4cplus: "); +static tchar const WARN_PREFIX[] = LOG4CPLUS_TEXT("log4cplus:WARN "); +static tchar const ERR_PREFIX[] = LOG4CPLUS_TEXT("log4cplus:ERROR "); + +} // namespace + + + +/////////////////////////////////////////////////////////////////////////////// +// static methods +/////////////////////////////////////////////////////////////////////////////// + +SharedObjectPtr +LogLog::getLogLog() +{ + static SharedObjectPtr singleton(new LogLog()); + return singleton; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::LogLog ctor and dtor +/////////////////////////////////////////////////////////////////////////////// + +LogLog::LogLog() + : mutex(LOG4CPLUS_MUTEX_CREATE), + debugEnabled(false), + quietMode(false) +{ +} + + +LogLog::~LogLog() +{ + LOG4CPLUS_MUTEX_FREE( mutex ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::LogLog public methods +/////////////////////////////////////////////////////////////////////////////// + +void +LogLog::setInternalDebugging(bool enabled) +{ + debugEnabled = enabled; +} + + +void +LogLog::setQuietMode(bool quietModeVal) +{ + quietMode = quietModeVal; +} + + +void +LogLog::debug(const log4cplus::tstring& msg) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + if(debugEnabled && !quietMode) { + tcout << PREFIX << msg << endl; + } + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +void +LogLog::warn(const log4cplus::tstring& msg) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + if(quietMode) return; + + tcerr << WARN_PREFIX << msg << endl; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +void +LogLog::error(const log4cplus::tstring& msg) +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + if(quietMode) return; + + tcerr << ERR_PREFIX << msg << endl; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + diff --git a/libs/log4cplus/src/logloguser.cxx b/libs/log4cplus/src/logloguser.cxx new file mode 100644 index 0000000..1f1acb3 --- /dev/null +++ b/libs/log4cplus/src/logloguser.cxx @@ -0,0 +1,80 @@ +// Module: Log4CPLUS +// File: logloguser.cxx +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 +#include +#include + +using namespace std; +using namespace log4cplus; +using namespace log4cplus::helpers; + +typedef SharedObjectPtr LogLogPtr; + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::LogLogUser ctor and dtor +/////////////////////////////////////////////////////////////////////////////// + +LogLogUser::LogLogUser() +{ + loglogRef = new SharedObjectPtr(LogLog::getLogLog()); +} + + +LogLogUser::LogLogUser(const LogLogUser& rhs) +{ + loglogRef = new SharedObjectPtr(*static_cast(rhs.loglogRef)); +} + + +LogLogUser::~LogLogUser() +{ + delete static_cast(loglogRef); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::LogLogUser public methods +/////////////////////////////////////////////////////////////////////////////// + +LogLog& +LogLogUser::getLogLog() const +{ + LogLogPtr* ptr = static_cast(loglogRef); + return **ptr; +} + + +LogLogUser& +LogLogUser::operator=(const LogLogUser& rhs) +{ + if(this == &rhs) { + return *this; + } + + delete static_cast(loglogRef); + loglogRef = new SharedObjectPtr(*static_cast(rhs.loglogRef)); + + return *this; +} + diff --git a/libs/log4cplus/src/ndc.cxx b/libs/log4cplus/src/ndc.cxx new file mode 100644 index 0000000..d9e5db7 --- /dev/null +++ b/libs/log4cplus/src/ndc.cxx @@ -0,0 +1,329 @@ +// Module: Log4CPLUS +// File: ndc.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include +#include + +using namespace log4cplus; +using namespace log4cplus::helpers; + + + +/////////////////////////////////////////////////////////////////////////////// +// public methods +/////////////////////////////////////////////////////////////////////////////// + +NDC& +log4cplus::getNDC() +{ + static NDC singleton; + return singleton; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::DiagnosticContext ctors +/////////////////////////////////////////////////////////////////////////////// + +DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_, DiagnosticContext* parent) + : message(message_), + fullMessage( ( (parent == NULL) + ? message + : parent->fullMessage + LOG4CPLUS_TEXT(" ") + message) ) +{ +} + + +DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_) + : message(message_), + fullMessage(message) +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::NDC ctor and dtor +/////////////////////////////////////////////////////////////////////////////// + +NDC::NDC() + : threadLocal(LOG4CPLUS_THREAD_LOCAL_INIT (0)) +{ +} + + +NDC::~NDC() +{ + LOG4CPLUS_THREAD_LOCAL_CLEANUP( threadLocal ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::NDC public methods +/////////////////////////////////////////////////////////////////////////////// + +void +NDC::clear() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL) { + delete ptr; + LOG4CPLUS_SET_THREAD_LOCAL_VALUE( threadLocal, NULL ); + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::clear()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::clear()- exception occured")); + } +} + + +DiagnosticContextStack +NDC::cloneStack() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL) { + return DiagnosticContextStack(*ptr); + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::cloneStack()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::cloneStack()- exception occured")); + } + + return DiagnosticContextStack(); +} + + +void +NDC::inherit(const DiagnosticContextStack& stack) +{ + try { + DiagnosticContextStack* ptr = getPtr(); + delete ptr; + + ptr = new DiagnosticContextStack(stack); + LOG4CPLUS_SET_THREAD_LOCAL_VALUE( threadLocal, ptr ); + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::inherit()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::inherit()- exception occured")); + } +} + + +log4cplus::tstring +NDC::get() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL && !ptr->empty()) { + return ptr->top().fullMessage; + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::get()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::get()- exception occured")); + } + + return LOG4CPLUS_TEXT(""); +} + + +size_t +NDC::getDepth() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL) { + return ptr->size(); + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::getDepth()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::getDepth()- exception occured")); + } + + return 0; +} + + +log4cplus::tstring +NDC::pop() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL && !ptr->empty()) { + DiagnosticContext dc = ptr->top(); + ptr->pop(); + if(ptr->empty()) { + // If the NDC stack is empty we will delete it so that we can avoid + // most memory leaks if Threads don't call remove when exiting + delete ptr; + LOG4CPLUS_SET_THREAD_LOCAL_VALUE( threadLocal, NULL ); + } + return dc.message; + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::pop()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::pop()- exception occured")); + } + + return LOG4CPLUS_TEXT(""); +} + + +log4cplus::tstring +NDC::peek() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL && !ptr->empty()) { + return ptr->top().message; + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::peek()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::peek()- exception occured")); + } + + return LOG4CPLUS_TEXT(""); +} + + +void +NDC::push(const log4cplus::tstring& message) +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr == NULL) { + ptr = new DiagnosticContextStack(); + LOG4CPLUS_SET_THREAD_LOCAL_VALUE( threadLocal, ptr ); + } + + if(ptr->empty()) { + ptr->push( DiagnosticContext(message, NULL) ); + } + else { + DiagnosticContext dc = ptr->top(); + ptr->push( DiagnosticContext(message, &dc) ); + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::push()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::push()- exception occured")); + } +} + + +void +NDC::remove() +{ + try { + DiagnosticContextStack* ptr = getPtr(); + delete ptr; + LOG4CPLUS_SET_THREAD_LOCAL_VALUE( threadLocal, NULL ); + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::remove()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::remove()- exception occured")); + } +} + + +void +NDC::setMaxDepth(size_t maxDepth) +{ + try { + DiagnosticContextStack* ptr = getPtr(); + if(ptr != NULL) { + while(maxDepth < ptr->size()) { + ptr->pop(); + } + } + } + catch(std::exception& e) { + getLogLog().error( LOG4CPLUS_TEXT("NDC::setMaxDepth()- exception occured: ") + + LOG4CPLUS_C_STR_TO_TSTRING(e.what())); + } + catch(...) { + getLogLog().error(LOG4CPLUS_TEXT("NDC::setMaxDepth()- exception occured")); + } +} + + +DiagnosticContextStack* NDC::getPtr() +{ + return static_cast + (LOG4CPLUS_GET_THREAD_LOCAL_VALUE( threadLocal )); +} + + +// +// +// + +NDCContextCreator::NDCContextCreator(const log4cplus::tstring& msg) +{ + getNDC().push(msg); +} + + +NDCContextCreator::~NDCContextCreator() +{ + getNDC().pop(); +} diff --git a/libs/log4cplus/src/nteventlogappender.cxx b/libs/log4cplus/src/nteventlogappender.cxx new file mode 100644 index 0000000..1b9a7dc --- /dev/null +++ b/libs/log4cplus/src/nteventlogappender.cxx @@ -0,0 +1,348 @@ +// Module: LOG4CPLUS +// File: nteventlogappender.cxx +// Created: 4/2003 +// Author: Michael CATANZARITI +// +// Copyright 2003-2010 Michael CATANZARITI +// +// 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 +#include +#include +#include +#include + + +#if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG) + +using namespace log4cplus; +using namespace log4cplus::spi; +using namespace log4cplus::helpers; + + +////////////////////////////////////////////////////////////////////////////// +// File LOCAL methods +////////////////////////////////////////////////////////////////////////////// + +namespace { + + bool + FreeSid(SID* pSid) + { + return ::HeapFree(GetProcessHeap(), 0, (LPVOID)pSid) != 0; + } + + + bool + CopySid(SID** ppDstSid, SID* pSrcSid) + { + bool bSuccess = false; + + DWORD dwLength = ::GetLengthSid(pSrcSid); + *ppDstSid = (SID *) ::HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, dwLength); + + if(::CopySid(dwLength, *ppDstSid, pSrcSid)) { + bSuccess = true; + } + else { + FreeSid(*ppDstSid); + } + + return bSuccess; + } + + + + bool + GetCurrentUserSID(SID** ppSid) + { + bool bSuccess = false; + + // Pseudohandle so don't need to close it + HANDLE hProcess = ::GetCurrentProcess(); + HANDLE hToken = NULL; + if(::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { + // Get the required size + DWORD tusize = 0; + GetTokenInformation(hToken, TokenUser, NULL, 0, &tusize); + TOKEN_USER* ptu = (TOKEN_USER*)new BYTE[tusize]; + + if(GetTokenInformation(hToken, TokenUser, (LPVOID)ptu, tusize, &tusize)) { + bSuccess = CopySid(ppSid, (SID *)ptu->User.Sid); + } + + CloseHandle(hToken); + delete [] ptu; + } + + return bSuccess; + } + + + + + + HKEY + regGetKey(const log4cplus::tstring& subkey, DWORD* disposition) + { + HKEY hkey = 0; + RegCreateKeyEx(HKEY_LOCAL_MACHINE, + subkey.c_str(), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, + NULL, + &hkey, + disposition); + return hkey; + } + + + + void + regSetString(HKEY hkey, const log4cplus::tstring& name, const log4cplus::tstring& value) + { + RegSetValueEx(hkey, + name.c_str(), + 0, + REG_SZ, + (LPBYTE)value.c_str(), + static_cast(value.length() * sizeof(tchar))); + } + + + + void + regSetDword(HKEY hkey, const log4cplus::tstring& name, DWORD value) + { + RegSetValueEx(hkey, + name.c_str(), + 0, + REG_DWORD, + (LPBYTE)&value, + sizeof(DWORD)); + } + +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::NTEventLogAppender ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +NTEventLogAppender::NTEventLogAppender(const log4cplus::tstring& server, + const log4cplus::tstring& log, + const log4cplus::tstring& source) +: server(server), + log(log), + source(source), + hEventLog(NULL), + pCurrentUserSID(NULL) +{ + init(); +} + + + +NTEventLogAppender::NTEventLogAppender(const Properties properties) +: Appender(properties), + hEventLog(NULL), + pCurrentUserSID(NULL) +{ + server = properties.getProperty( LOG4CPLUS_TEXT("server") ); + log = properties.getProperty( LOG4CPLUS_TEXT("log") ); + source = properties.getProperty( LOG4CPLUS_TEXT("source") ); + + init(); +} + + + +void +NTEventLogAppender::init() +{ + if(source.empty()) { + getLogLog().warn( LOG4CPLUS_TEXT("Source option not set for appender [") + + name + + LOG4CPLUS_TEXT("].")); + return; + } + + if(log.empty ()) { + log = LOG4CPLUS_TEXT("Application"); + } + + // current user security identifier + GetCurrentUserSID(&pCurrentUserSID); + + addRegistryInfo(); + + hEventLog = ::RegisterEventSource(server.empty () ? 0 : server.c_str(), + source.c_str()); + if (! hEventLog || hEventLog == HANDLE(ERROR_INVALID_HANDLE)) + getLogLog().warn (LOG4CPLUS_TEXT("Event source registration failed.")); +} + + + +NTEventLogAppender::~NTEventLogAppender() +{ + destructorImpl(); + + if(pCurrentUserSID != NULL) { + FreeSid(pCurrentUserSID); + pCurrentUserSID = NULL; + } +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::NTEventLogAppender public methods +////////////////////////////////////////////////////////////////////////////// + +void +NTEventLogAppender::close() +{ + if(hEventLog != NULL) { + ::DeregisterEventSource(hEventLog); + hEventLog = NULL; + } + closed = true; +} + + + +////////////////////////////////////////////////////////////////////////////// +// log4cplus::NTEventLogAppender protected methods +////////////////////////////////////////////////////////////////////////////// + +void +NTEventLogAppender::append(const InternalLoggingEvent& event) +{ + if(hEventLog == NULL) { + getLogLog().warn(LOG4CPLUS_TEXT("NT EventLog not opened.")); + return; + } + + tostringstream buf; + layout->formatAndAppend(buf, event); + tstring sz = buf.str(); + const tchar * s = sz.c_str(); + + BOOL bSuccess = ::ReportEvent(hEventLog, + getEventType(event), + getEventCategory(event), + 0x1000, + pCurrentUserSID, + 1, + 0, + &s, + NULL); + + if(!bSuccess) { + getLogLog().error(LOG4CPLUS_TEXT("Cannot report event in NT EventLog.")); + } +} + + + + +WORD +NTEventLogAppender::getEventType(const InternalLoggingEvent& event) +{ + WORD ret_val; + + switch ((int)event.getLogLevel()) + { + case FATAL_LOG_LEVEL: + case ERROR_LOG_LEVEL: + ret_val = EVENTLOG_ERROR_TYPE; + break; + case WARN_LOG_LEVEL: + ret_val = EVENTLOG_WARNING_TYPE; + break; + case INFO_LOG_LEVEL: + case DEBUG_LOG_LEVEL: + default: + ret_val = EVENTLOG_INFORMATION_TYPE; + break; + } + + return ret_val; +} + + + +WORD +NTEventLogAppender::getEventCategory(const InternalLoggingEvent& event) +{ + WORD ret_val; + + switch (event.getLogLevel()) + { + case FATAL_LOG_LEVEL: + ret_val = 1; + break; + case ERROR_LOG_LEVEL: + ret_val = 2; + break; + case WARN_LOG_LEVEL: + ret_val = 3; + break; + case INFO_LOG_LEVEL: + ret_val = 4; + break; + case DEBUG_LOG_LEVEL: + default: + ret_val = 5; + break; + } + + return ret_val; +} + + +// Add this source with appropriate configuration keys to the registry. +void +NTEventLogAppender::addRegistryInfo() +{ + DWORD disposition; + HKEY hkey = 0; + tstring subkey = LOG4CPLUS_TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\") + + log + + LOG4CPLUS_TEXT("\\") + + source; + + hkey = regGetKey(subkey, &disposition); + if(disposition == REG_CREATED_NEW_KEY) { + regSetString(hkey, + LOG4CPLUS_TEXT("EventMessageFile"), + LOG4CPLUS_TEXT("NTEventLogAppender.dll")); + regSetString(hkey, + LOG4CPLUS_TEXT("CategoryMessageFile"), + LOG4CPLUS_TEXT("NTEventLogAppender.dll")); + regSetDword(hkey, LOG4CPLUS_TEXT("TypesSupported"), (DWORD)7); + regSetDword(hkey, LOG4CPLUS_TEXT("CategoryCount"), (DWORD)5); + } + + RegCloseKey(hkey); + return; +} + + +#endif diff --git a/libs/log4cplus/src/nullappender.cxx b/libs/log4cplus/src/nullappender.cxx new file mode 100644 index 0000000..c2944f8 --- /dev/null +++ b/libs/log4cplus/src/nullappender.cxx @@ -0,0 +1,74 @@ +// Module: Log4CPLUS +// File: nullappender.cxx +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 + +using namespace std; +using namespace log4cplus; +using namespace log4cplus::helpers; + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::NullAppender ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +log4cplus::NullAppender::NullAppender() +{ +} + + +log4cplus::NullAppender::NullAppender(const log4cplus::helpers::Properties& properties) +: Appender(properties) +{ +} + + + +log4cplus::NullAppender::~NullAppender() +{ + destructorImpl(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::NullAppender public methods +/////////////////////////////////////////////////////////////////////////////// + +void +log4cplus::NullAppender::close() +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::NullAppender protected methods +/////////////////////////////////////////////////////////////////////////////// + +// This method does not need to be locked since it is called by +// doAppend() which performs the locking +void +log4cplus::NullAppender::append(const spi::InternalLoggingEvent&) +{ +} + + diff --git a/libs/log4cplus/src/objectregistry.cxx b/libs/log4cplus/src/objectregistry.cxx new file mode 100644 index 0000000..ad365a6 --- /dev/null +++ b/libs/log4cplus/src/objectregistry.cxx @@ -0,0 +1,113 @@ +// Module: Log4CPLUS +// File: objectregistry.cxx +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 + +using namespace std; +using namespace log4cplus::spi; + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::spi::ObjectRegistryBase ctor and dtor +/////////////////////////////////////////////////////////////////////////////// + +log4cplus::spi::ObjectRegistryBase::ObjectRegistryBase() + : mutex(LOG4CPLUS_MUTEX_CREATE) +{ +} + + +log4cplus::spi::ObjectRegistryBase::~ObjectRegistryBase() +{ + LOG4CPLUS_MUTEX_FREE( mutex ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::spi::ObjectRegistryBase public methods +/////////////////////////////////////////////////////////////////////////////// + +bool +log4cplus::spi::ObjectRegistryBase::exists(const log4cplus::tstring& name) const +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + return data.find(name) != data.end(); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +std::vector +log4cplus::spi::ObjectRegistryBase::getAllNames() const +{ + std::vector tmp; + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + for(ObjectMap::const_iterator it=data.begin(); it!=data.end(); ++it) + tmp.push_back( (*it).first ); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; + return tmp; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::spi::ObjectRegistryBase protected methods +/////////////////////////////////////////////////////////////////////////////// + +bool +log4cplus::spi::ObjectRegistryBase::putVal(const log4cplus::tstring& name, void* object) +{ + ObjectMap::value_type value(name, object); + std::pair ret; + + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + ret = data.insert(value); + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; + + if (! ret.second) + deleteObject( value.second ); + return ret.second; +} + + +void* +log4cplus::spi::ObjectRegistryBase::getVal(const log4cplus::tstring& name) const +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + ObjectMap::const_iterator it (data.find (name)); + if (it != data.end ()) + return it->second; + else + return 0; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + + +void +log4cplus::spi::ObjectRegistryBase::clear() +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex ) + for(ObjectMap::iterator it=data.begin(); it!=data.end(); ++it) { + deleteObject( (*it).second ); + } + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} diff --git a/libs/log4cplus/src/patternlayout.cxx b/libs/log4cplus/src/patternlayout.cxx new file mode 100644 index 0000000..e0b66c4 --- /dev/null +++ b/libs/log4cplus/src/patternlayout.cxx @@ -0,0 +1,957 @@ +// Module: Log4CPLUS +// File: patternlayout.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include + +#ifdef LOG4CPLUS_HAVE_STDLIB_H +#include +#endif +#include + +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LOG4CPLUS_HAVE_UNISTD_H +#include +#endif + + +namespace +{ + +static +#if defined (_WIN32) +DWORD +get_process_id () +{ + return GetCurrentProcessId (); +} + +#elif defined (LOG4CPLUS_HAVE_GETPID) +pid_t +get_process_id () +{ + return getpid (); +} + +#else +int +get_process_id () +{ + return 0; +} + +#endif + + +static +log4cplus::tstring +get_basename (const log4cplus::tstring& filename) +{ +#if defined(_WIN32) + log4cplus::tchar const dir_sep(LOG4CPLUS_TEXT('\\')); +#else + log4cplus::tchar const dir_sep(LOG4CPLUS_TEXT('/')); +#endif + + log4cplus::tstring::size_type pos = filename.rfind(dir_sep); + if (pos != log4cplus::tstring::npos) + return filename.substr(pos+1); + else + return filename; +} + + +} // namespace + + +using namespace std; +using namespace log4cplus; +using namespace log4cplus::helpers; +using namespace log4cplus::spi; + + +#define ESCAPE_CHAR LOG4CPLUS_TEXT('%') + + +namespace log4cplus { + namespace pattern { + + /** + * This is used by PatternConverter class to inform them how to format + * their output. + */ + struct FormattingInfo { + int minLen; + size_t maxLen; + bool leftAlign; + FormattingInfo() { reset(); } + + void reset(); + void dump(log4cplus::helpers::LogLog&); + }; + + + + /** + * This is the base class of all "Converter" classes that format a + * field of InternalLoggingEvent objects. In fact, the PatternLayout + * class simply uses an array of PatternConverter objects to format + * and append a logging event. + */ + class PatternConverter : protected log4cplus::helpers::LogLogUser { + public: + PatternConverter(const FormattingInfo& info); + virtual ~PatternConverter() {} + void formatAndAppend(log4cplus::tostream& output, + const InternalLoggingEvent& event); + + protected: + virtual log4cplus::tstring convert(const InternalLoggingEvent& event) = 0; + + private: + int minLen; + size_t maxLen; + bool leftAlign; + }; + + + + /** + * This PatternConverter returns a constant string. + */ + class LiteralPatternConverter : public PatternConverter { + public: + LiteralPatternConverter(const log4cplus::tstring& str); + virtual log4cplus::tstring convert(const InternalLoggingEvent&) { + return str; + } + + private: + log4cplus::tstring str; + }; + + + + /** + * This PatternConverter is used to format most of the "simple" fields + * found in the InternalLoggingEvent object. + */ + class BasicPatternConverter : public PatternConverter { + public: + enum Type { THREAD_CONVERTER, + PROCESS_CONVERTER, + LOGLEVEL_CONVERTER, + NDC_CONVERTER, + MESSAGE_CONVERTER, + NEWLINE_CONVERTER, + BASENAME_CONVERTER, + FILE_CONVERTER, + LINE_CONVERTER, + FULL_LOCATION_CONVERTER }; + BasicPatternConverter(const FormattingInfo& info, Type type); + virtual log4cplus::tstring convert(const InternalLoggingEvent& event); + + private: + // Disable copy + BasicPatternConverter(const BasicPatternConverter&); + BasicPatternConverter& operator=(BasicPatternConverter&); + + LogLevelManager& llmCache; + Type type; + }; + + + + /** + * This PatternConverter is used to format the Logger field found in + * the InternalLoggingEvent object. + */ + class LoggerPatternConverter : public PatternConverter { + public: + LoggerPatternConverter(const FormattingInfo& info, int precision); + virtual log4cplus::tstring convert(const InternalLoggingEvent& event); + + private: + int precision; + }; + + + + /** + * This PatternConverter is used to format the timestamp field found in + * the InternalLoggingEvent object. It will be formatted according to + * the specified "pattern". + */ + class DatePatternConverter : public PatternConverter { + public: + DatePatternConverter(const FormattingInfo& info, + const log4cplus::tstring& pattern, + bool use_gmtime); + virtual log4cplus::tstring convert(const InternalLoggingEvent& event); + + private: + bool use_gmtime; + log4cplus::tstring format; + }; + + + + /** + * This PatternConverter is used to format the hostname field. + */ + class HostnamePatternConverter : public PatternConverter { + public: + HostnamePatternConverter(const FormattingInfo& info, bool fqdn); + virtual log4cplus::tstring convert(const InternalLoggingEvent& event); + + private: + log4cplus::tstring hostname_; + }; + + + + /** + * This PatternConverter is used to format the NDC field found in + * the InternalLoggingEvent object, optionally limited to + * \c precision levels (using space to separate levels). + */ + class NDCPatternConverter : public PatternConverter { + public: + NDCPatternConverter(const FormattingInfo& info, int precision); + virtual log4cplus::tstring convert(const InternalLoggingEvent& event); + + private: + int precision; + }; + + + + /** + * This class parses a "pattern" string into an array of + * PatternConverter objects. + *

+ * @see PatternLayout for the formatting of the "pattern" string. + */ + class PatternParser : protected log4cplus::helpers::LogLogUser { + public: + PatternParser(const log4cplus::tstring& pattern, unsigned ndcMaxDepth); + std::vector parse(); + + private: + // Types + enum ParserState { LITERAL_STATE, + CONVERTER_STATE, + DOT_STATE, + MIN_STATE, + MAX_STATE }; + + // Methods + log4cplus::tstring extractOption(); + int extractPrecisionOption(); + void finalizeConverter(log4cplus::tchar c); + + // Data + log4cplus::tstring pattern; + FormattingInfo formattingInfo; + std::vector list; + ParserState state; + tstring::size_type pos; + log4cplus::tstring currentLiteral; + unsigned ndcMaxDepth; + }; + } +} +using namespace log4cplus::pattern; +typedef std::vector PatternConverterList; + + + +//////////////////////////////////////////////// +// PatternConverter methods: +//////////////////////////////////////////////// + +void +log4cplus::pattern::FormattingInfo::reset() { + minLen = -1; + maxLen = 0x7FFFFFFF; + leftAlign = false; +} + + +void +log4cplus::pattern::FormattingInfo::dump(log4cplus::helpers::LogLog& loglog) { + log4cplus::tostringstream buf; + buf << LOG4CPLUS_TEXT("min=") << minLen + << LOG4CPLUS_TEXT(", max=") << maxLen + << LOG4CPLUS_TEXT(", leftAlign=") + << (leftAlign ? LOG4CPLUS_TEXT("true") : LOG4CPLUS_TEXT("false")); + loglog.debug(buf.str()); +} + + + + +//////////////////////////////////////////////// +// PatternConverter methods: +//////////////////////////////////////////////// + +log4cplus::pattern::PatternConverter::PatternConverter(const FormattingInfo& i) +{ + minLen = i.minLen; + maxLen = i.maxLen; + leftAlign = i.leftAlign; +} + + + +void +log4cplus::pattern::PatternConverter::formatAndAppend + (log4cplus::tostream& output, const InternalLoggingEvent& event) +{ + log4cplus::tstring s = convert(event); + size_t len = s.length(); + + if(len > maxLen) { + output << s.substr(len - maxLen); + } + else if(static_cast(len) < minLen) { + if(leftAlign) { + output << s; + output << log4cplus::tstring(minLen - len, LOG4CPLUS_TEXT(' ')); + } + else { + output << log4cplus::tstring(minLen - len, LOG4CPLUS_TEXT(' ')); + output << s; + } + } + else { + output << s; + } +} + + + +//////////////////////////////////////////////// +// LiteralPatternConverter methods: +//////////////////////////////////////////////// + +log4cplus::pattern::LiteralPatternConverter::LiteralPatternConverter + (const log4cplus::tstring& str_) +: PatternConverter(FormattingInfo()), + str(str_) +{ +} + + + +//////////////////////////////////////////////// +// BasicPatternConverter methods: +//////////////////////////////////////////////// + +log4cplus::pattern::BasicPatternConverter::BasicPatternConverter + (const FormattingInfo& info, Type type_) +: PatternConverter(info), + llmCache(getLogLevelManager()), + type(type_) +{ +} + + + +log4cplus::tstring +log4cplus::pattern::BasicPatternConverter::convert + (const InternalLoggingEvent& event) +{ + switch(type) { + case LOGLEVEL_CONVERTER: return llmCache.toString(event.getLogLevel()); + case NDC_CONVERTER: return event.getNDC(); + case MESSAGE_CONVERTER: return event.getMessage(); + case NEWLINE_CONVERTER: return LOG4CPLUS_TEXT("\n"); + case BASENAME_CONVERTER: return get_basename(event.getFile()); + case FILE_CONVERTER: return event.getFile(); + case THREAD_CONVERTER: return event.getThread(); + case PROCESS_CONVERTER: return convertIntegerToString(get_process_id ()); + + case LINE_CONVERTER: + { + int line = event.getLine(); + if(line != -1) { + return convertIntegerToString(line); + } + else { + return log4cplus::tstring(); + } + } + + case FULL_LOCATION_CONVERTER: + { + tstring const & filename = event.getFile(); + if(! filename.empty ()) { + return filename + + LOG4CPLUS_TEXT(":") + + convertIntegerToString(event.getLine()); + } + else { + return LOG4CPLUS_TEXT(":"); + } + } + } + + return LOG4CPLUS_TEXT("INTERNAL LOG4CPLUS ERROR"); +} + + + +//////////////////////////////////////////////// +// LoggerPatternConverter methods: +//////////////////////////////////////////////// + +log4cplus::pattern::LoggerPatternConverter::LoggerPatternConverter + (const FormattingInfo& info, int precision_) +: PatternConverter(info), + precision(precision_) +{ +} + + + +log4cplus::tstring +log4cplus::pattern::LoggerPatternConverter::convert + (const InternalLoggingEvent& event) +{ + const log4cplus::tstring& name = event.getLoggerName(); + if (precision <= 0) { + return name; + } + else { + size_t len = name.length(); + + // We substract 1 from 'len' when assigning to 'end' to avoid out of + // bounds exception in return r.substring(end+1, len). This can happen + // if precision is 1 and the logger name ends with a dot. + tstring::size_type end = len - 1; + for(int i=precision; i>0; --i) { + end = name.rfind(LOG4CPLUS_TEXT('.'), end - 1); + if(end == tstring::npos) { + return name; + } + } + return name.substr(end + 1); + } +} + + + +//////////////////////////////////////////////// +// DatePatternConverter methods: +//////////////////////////////////////////////// + + +log4cplus::pattern::DatePatternConverter::DatePatternConverter + (const FormattingInfo& info, + const log4cplus::tstring& pattern, + bool use_gmtime_) +: PatternConverter(info), + use_gmtime(use_gmtime_), + format(pattern) +{ +} + + + +log4cplus::tstring +log4cplus::pattern::DatePatternConverter::convert + (const InternalLoggingEvent& event) +{ + return event.getTimestamp().getFormattedTime(format, use_gmtime); +} + + + + +//////////////////////////////////////////////// +// HostnamePatternConverter methods: +//////////////////////////////////////////////// + +log4cplus::pattern::HostnamePatternConverter::HostnamePatternConverter ( + const FormattingInfo& info, bool fqdn) + : PatternConverter(info) + , hostname_ (helpers::getHostname (fqdn)) +{ } + + +log4cplus::tstring +log4cplus::pattern::HostnamePatternConverter::convert ( + const InternalLoggingEvent &) +{ + return hostname_; +} + + + +//////////////////////////////////////////////// +// NDCPatternConverter methods: +//////////////////////////////////////////////// + +log4cplus::pattern::NDCPatternConverter::NDCPatternConverter ( + const FormattingInfo& info, int precision_) + : PatternConverter(info) + , precision(precision_) +{ } + + +log4cplus::tstring +log4cplus::pattern::NDCPatternConverter::convert ( + const InternalLoggingEvent& event) +{ + const log4cplus::tstring& text = event.getNDC(); + if (precision <= 0) + return text; + else + { + tstring::size_type p = text.find(LOG4CPLUS_TEXT(' ')); + for (int i = 1; i < precision && p != tstring::npos; ++i) + p = text.find(LOG4CPLUS_TEXT(' '), p + 1); + + return text.substr(0, p); + } +} + + + +//////////////////////////////////////////////// +// PatternParser methods: +//////////////////////////////////////////////// + +log4cplus::pattern::PatternParser::PatternParser( + const log4cplus::tstring& pattern_, unsigned ndcMaxDepth_) + : pattern(pattern_) + , state(LITERAL_STATE) + , pos(0) + , ndcMaxDepth (ndcMaxDepth_) +{ +} + + + +log4cplus::tstring +log4cplus::pattern::PatternParser::extractOption() +{ + if ( (pos < pattern.length()) + && (pattern[pos] == LOG4CPLUS_TEXT('{'))) + { + tstring::size_type end = pattern.find_first_of(LOG4CPLUS_TEXT('}'), pos); + if (end != tstring::npos) { + log4cplus::tstring r = pattern.substr(pos + 1, end - pos - 1); + pos = end + 1; + return r; + } + else { + log4cplus::tostringstream buf; + buf << LOG4CPLUS_TEXT("No matching '}' found in conversion pattern string \"") + << pattern + << LOG4CPLUS_TEXT("\""); + getLogLog().error(buf.str()); + pos = pattern.length(); + } + } + + return LOG4CPLUS_TEXT(""); +} + + +int +log4cplus::pattern::PatternParser::extractPrecisionOption() +{ + log4cplus::tstring opt = extractOption(); + int r = 0; + if(! opt.empty ()) { + r = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(opt).c_str()); + } + return r; +} + + + +PatternConverterList +log4cplus::pattern::PatternParser::parse() +{ + tchar c; + pos = 0; + while(pos < pattern.length()) { + c = pattern[pos++]; + switch (state) { + case LITERAL_STATE : + // In literal state, the last char is always a literal. + if(pos == pattern.length()) { + currentLiteral += c; + continue; + } + if(c == ESCAPE_CHAR) { + // peek at the next char. + switch (pattern[pos]) { + case ESCAPE_CHAR: + currentLiteral += c; + pos++; // move pointer + break; + default: + if(! currentLiteral.empty ()) { + list.push_back + (new LiteralPatternConverter(currentLiteral)); + //getLogLog().debug("Parsed LITERAL converter: \"" + // +currentLiteral+"\"."); + } + currentLiteral.resize(0); + currentLiteral += c; // append % + state = CONVERTER_STATE; + formattingInfo.reset(); + } + } + else { + currentLiteral += c; + } + break; + + case CONVERTER_STATE: + currentLiteral += c; + switch (c) { + case LOG4CPLUS_TEXT('-'): + formattingInfo.leftAlign = true; + break; + case LOG4CPLUS_TEXT('.'): + state = DOT_STATE; + break; + default: + if(c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) { + formattingInfo.minLen = c - LOG4CPLUS_TEXT('0'); + state = MIN_STATE; + } + else { + finalizeConverter(c); + } + } // switch + break; + + case MIN_STATE: + currentLiteral += c; + if (c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) { + formattingInfo.minLen = formattingInfo.minLen * 10 + (c - LOG4CPLUS_TEXT('0')); + } + else if(c == LOG4CPLUS_TEXT('.')) { + state = DOT_STATE; + } + else { + finalizeConverter(c); + } + break; + + case DOT_STATE: + currentLiteral += c; + if(c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) { + formattingInfo.maxLen = c - LOG4CPLUS_TEXT('0'); + state = MAX_STATE; + } + else { + log4cplus::tostringstream buf; + buf << LOG4CPLUS_TEXT("Error occured in position ") + << pos + << LOG4CPLUS_TEXT(".\n Was expecting digit, instead got char \"") + << c + << LOG4CPLUS_TEXT("\"."); + getLogLog().error(buf.str()); + state = LITERAL_STATE; + } + break; + + case MAX_STATE: + currentLiteral += c; + if (c >= LOG4CPLUS_TEXT('0') && c <= LOG4CPLUS_TEXT('9')) + formattingInfo.maxLen = formattingInfo.maxLen * 10 + (c - LOG4CPLUS_TEXT('0')); + else { + finalizeConverter(c); + state = LITERAL_STATE; + } + break; + } // end switch + } // end while + + if(! currentLiteral.empty ()) { + list.push_back(new LiteralPatternConverter(currentLiteral)); + //getLogLog().debug("Parsed LITERAL converter: \""+currentLiteral+"\"."); + } + + return list; +} + + + +void +log4cplus::pattern::PatternParser::finalizeConverter(log4cplus::tchar c) +{ + PatternConverter* pc = 0; + switch (c) { + case LOG4CPLUS_TEXT('b'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::BASENAME_CONVERTER); + //getLogLog().debug("BASENAME converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('c'): + pc = new LoggerPatternConverter(formattingInfo, + extractPrecisionOption()); + getLogLog().debug( LOG4CPLUS_TEXT("LOGGER converter.") ); + formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('d'): + case LOG4CPLUS_TEXT('D'): + { + log4cplus::tstring dOpt = extractOption(); + if(dOpt.empty ()) { + dOpt = LOG4CPLUS_TEXT("%Y-%m-%d %H:%M:%S"); + } + bool use_gmtime = c == LOG4CPLUS_TEXT('d'); + pc = new DatePatternConverter(formattingInfo, dOpt, use_gmtime); + //if(use_gmtime) { + // getLogLog().debug("GMT DATE converter."); + //} + //else { + // getLogLog().debug("LOCAL DATE converter."); + //} + //formattingInfo.dump(getLogLog()); + } + break; + + case LOG4CPLUS_TEXT('F'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::FILE_CONVERTER); + //getLogLog().debug("FILE NAME converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('h'): + case LOG4CPLUS_TEXT('H'): + { + bool fqdn = (c == LOG4CPLUS_TEXT('H')); + pc = new HostnamePatternConverter(formattingInfo, fqdn); + // getLogLog().debug( LOG4CPLUS_TEXT("HOSTNAME converter.") ); + // formattingInfo.dump(getLogLog()); + } + break; + + case LOG4CPLUS_TEXT('i'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::PROCESS_CONVERTER); + //getLogLog().debug("PROCESS_CONVERTER converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('l'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::FULL_LOCATION_CONVERTER); + //getLogLog().debug("FULL LOCATION converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('L'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::LINE_CONVERTER); + //getLogLog().debug("LINE NUMBER converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('m'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::MESSAGE_CONVERTER); + //getLogLog().debug("MESSAGE converter."); + //formattingInfo.dump(getLogLog()); + break; + + // 'M' is METHOD converter in log4j. + // Not implemented. + case LOG4CPLUS_TEXT('M'): + goto not_implemented; + + case LOG4CPLUS_TEXT('n'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::NEWLINE_CONVERTER); + //getLogLog().debug("MESSAGE converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('p'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::LOGLEVEL_CONVERTER); + //getLogLog().debug("LOGLEVEL converter."); + //formattingInfo.dump(getLogLog()); + break; + + // 'r' is RELATIVE time converter in log4j. + // Not implemented. + case LOG4CPLUS_TEXT('r'): + goto not_implemented; + + case LOG4CPLUS_TEXT('t'): + pc = new BasicPatternConverter + (formattingInfo, + BasicPatternConverter::THREAD_CONVERTER); + //getLogLog().debug("THREAD converter."); + //formattingInfo.dump(getLogLog()); + break; + + case LOG4CPLUS_TEXT('x'): + pc = new NDCPatternConverter (formattingInfo, ndcMaxDepth); + //getLogLog().debug("NDC converter."); + break; + + // 'X' is MDC in log4j. + // Not implemented. + case LOG4CPLUS_TEXT('X'): + goto not_implemented; + +not_implemented:; + default: + log4cplus::tostringstream buf; + buf << LOG4CPLUS_TEXT("Unexpected char [") + << c + << LOG4CPLUS_TEXT("] at position ") + << pos + << LOG4CPLUS_TEXT(" in conversion patterrn."); + getLogLog().error(buf.str()); + pc = new LiteralPatternConverter(currentLiteral); + } + + currentLiteral.resize(0); + list.push_back(pc); + state = LITERAL_STATE; + formattingInfo.reset(); +} + + + + + +//////////////////////////////////////////////// +// PatternLayout methods: +//////////////////////////////////////////////// + +PatternLayout::PatternLayout(const log4cplus::tstring& pattern_) +{ + init(pattern_, 0); +} + + +PatternLayout::PatternLayout(const log4cplus::helpers::Properties& properties) +{ + unsigned ndcMaxDepth + = std::atoi (LOG4CPLUS_TSTRING_TO_STRING ( + properties.getProperty ( + LOG4CPLUS_TEXT ("NDCMaxDepth"), + LOG4CPLUS_TEXT ("0"))).c_str ()); + + bool hasPattern = properties.exists( LOG4CPLUS_TEXT("Pattern") ); + bool hasConversionPattern = properties.exists( LOG4CPLUS_TEXT("ConversionPattern") ); + + if(hasPattern) { + getLogLog().warn( LOG4CPLUS_TEXT("PatternLayout- the \"Pattern\" property has been deprecated. Use \"ConversionPattern\" instead.")); + } + + if(hasConversionPattern) { + init(properties.getProperty( LOG4CPLUS_TEXT("ConversionPattern") ), + ndcMaxDepth); + } + else if(hasPattern) { + init(properties.getProperty( LOG4CPLUS_TEXT("Pattern") ), ndcMaxDepth); + } + else { + throw std::runtime_error("ConversionPattern not specified in properties"); + } + +} + + +void +PatternLayout::init(const log4cplus::tstring& pattern_, unsigned ndcMaxDepth) +{ + this->pattern = pattern_; + this->parsedPattern = PatternParser(pattern, ndcMaxDepth).parse(); + + // Let's validate that our parser didn't give us any NULLs. If it did, + // we will convert them to a valid PatternConverter that does nothing so + // at least we don't core. + for(PatternConverterList::iterator it=parsedPattern.begin(); + it!=parsedPattern.end(); + ++it) + { + if( (*it) == 0 ) { + getLogLog().error(LOG4CPLUS_TEXT("Parsed Pattern created a NULL PatternConverter")); + (*it) = new LiteralPatternConverter( LOG4CPLUS_TEXT("") ); + } + } + if(parsedPattern.empty ()) { + getLogLog().warn(LOG4CPLUS_TEXT("PatternLayout pattern is empty. Using default...")); + parsedPattern.push_back + (new BasicPatternConverter(FormattingInfo(), + BasicPatternConverter::MESSAGE_CONVERTER)); + } +} + + + +PatternLayout::~PatternLayout() +{ + for(PatternConverterList::iterator it=parsedPattern.begin(); + it!=parsedPattern.end(); + ++it) + { + delete (*it); + } +} + + + +void +PatternLayout::formatAndAppend(log4cplus::tostream& output, + const InternalLoggingEvent& event) +{ + for(PatternConverterList::iterator it=parsedPattern.begin(); + it!=parsedPattern.end(); + ++it) + { + (*it)->formatAndAppend(output, event); + } +} + + diff --git a/libs/log4cplus/src/pointer.cxx b/libs/log4cplus/src/pointer.cxx new file mode 100644 index 0000000..fe1079f --- /dev/null +++ b/libs/log4cplus/src/pointer.cxx @@ -0,0 +1,70 @@ +// Module: Log4CPLUS +// File: pointer.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2009 Tad E. Smith +// +// 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 +#include +#include +#include + + +namespace log4cplus { namespace helpers { + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::SharedObject dtor +/////////////////////////////////////////////////////////////////////////////// + +SharedObject::~SharedObject() +{ + assert(count == 0); + LOG4CPLUS_MUTEX_FREE( access_mutex ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::helpers::SharedObject public methods +/////////////////////////////////////////////////////////////////////////////// + +void +SharedObject::addReference() const +{ + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ) + assert (count >= 0); + ++count; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + +void +SharedObject::removeReference() const +{ + bool destroy = false; + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ); + assert (count > 0); + if (--count == 0) + destroy = true; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; + if (destroy) + delete this; +} + + +} } // namespace log4cplus { namespace helpers diff --git a/libs/log4cplus/src/property.cxx b/libs/log4cplus/src/property.cxx new file mode 100644 index 0000000..1a5755a --- /dev/null +++ b/libs/log4cplus/src/property.cxx @@ -0,0 +1,241 @@ +// Module: Log4CPLUS +// File: property.cxx +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2010 Tad E. Smith +// +// 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 +#if defined (UNICODE) +# include +#else +# include +#endif +#include +#include + + +namespace log4cplus +{ + + +const tchar helpers::Properties::PROPERTIES_COMMENT_CHAR = LOG4CPLUS_TEXT('#'); + + +namespace +{ + + +static +int +is_space (tchar ch) +{ +#if defined (UNICODE) + return std::iswspace (ch); +#else + return std::isspace (static_cast(ch)); +#endif +} + + +static +void +trim_leading_ws (tstring & str) +{ + tstring::iterator it = str.begin (); + for (; it != str.end (); ++it) + { + if (! is_space (*it)) + break; + } + str.erase (str.begin (), it); +} + + +static +void +trim_trailing_ws (tstring & str) +{ + tstring::reverse_iterator rit = str.rbegin (); + for (; rit != str.rend (); ++rit) + { + if (! is_space (*rit)) + break; + } + str.erase (rit.base (), str.end ()); +} + + +static +void +trim_ws (tstring & str) +{ + trim_trailing_ws (str); + trim_leading_ws (str); +} + + +} // namespace + + + +namespace helpers +{ + +/////////////////////////////////////////////////////////////////////////////// +// Properties ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +Properties::Properties() +{ +} + + + +Properties::Properties(tistream& input) +{ + init(input); +} + + + +Properties::Properties(const tstring& inputFile) +{ + if (inputFile.empty ()) + return; + + tifstream file (LOG4CPLUS_TSTRING_TO_STRING(inputFile).c_str()); + init(file); +} + + + +void +Properties::init(tistream& input) +{ + if (! input) + return; + + tstring buffer; + while (std::getline (input, buffer)) + { + trim_leading_ws (buffer); + + tstring::size_type const buffLen = buffer.size (); + if (buffLen == 0 || buffer[0] == PROPERTIES_COMMENT_CHAR) + continue; + + // Check if we have a trailing \r because we are + // reading a properties file produced on Windows. + if (buffer[buffLen-1] == LOG4CPLUS_TEXT('\r')) + // Remove trailing 'Windows' \r. + buffer.resize (buffLen - 1); + + tstring::size_type const idx = buffer.find('='); + if (idx != tstring::npos) + { + tstring key = buffer.substr(0, idx); + tstring value = buffer.substr(idx + 1); + trim_trailing_ws (key); + trim_ws (value); + setProperty(key, value); + } + } +} + + + +Properties::~Properties() +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Properties public methods +/////////////////////////////////////////////////////////////////////////////// + +tstring +Properties::getProperty(const tstring& key) const +{ + StringMap::const_iterator it (data.find(key)); + if (it == data.end()) + return LOG4CPLUS_TEXT(""); + else + return it->second; +} + + + +tstring +Properties::getProperty(const tstring& key, + const tstring& defaultVal) const +{ + StringMap::const_iterator it (data.find (key)); + if (it == data.end ()) + return defaultVal; + else + return it->second; +} + + +std::vector +Properties::propertyNames() const +{ + std::vector tmp; + for (StringMap::const_iterator it=data.begin(); it!=data.end(); ++it) + tmp.push_back(it->first); + + return tmp; +} + + + +void +Properties::setProperty(const tstring& key, const tstring& value) +{ + data[key] = value; +} + + +bool +Properties::removeProperty(const tstring& key) +{ + return (data.erase(key) > 0); +} + + +Properties +Properties::getPropertySubset( + const tstring& prefix) const +{ + Properties ret; + std::vector const keys = propertyNames(); + size_t const prefix_len = prefix.size (); + for (std::vector::const_iterator it = keys.begin(); + it != keys.end(); ++it) + { + int result = it->compare (0, prefix_len, prefix); + if (result == 0) + ret.setProperty (it->substr (prefix_len), getProperty(*it)); + } + + return ret; +} + +} // namespace helpers + +} // namespace log4cplus diff --git a/libs/log4cplus/src/rootlogger.cxx b/libs/log4cplus/src/rootlogger.cxx new file mode 100644 index 0000000..b86d230 --- /dev/null +++ b/libs/log4cplus/src/rootlogger.cxx @@ -0,0 +1,62 @@ +// Module: Log4CPLUS +// File: rootlogger.cxx +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 + +using namespace log4cplus; +using namespace log4cplus::helpers; +using namespace log4cplus::spi; + + + +////////////////////////////////////////////////////////////////////////////// +// RootLogger Constructor +////////////////////////////////////////////////////////////////////////////// + +RootLogger::RootLogger(Hierarchy& h, LogLevel ll_) +: LoggerImpl(LOG4CPLUS_TEXT("root"), h) +{ + setLogLevel(ll_); +} + + + +////////////////////////////////////////////////////////////////////////////// +// Logger Methods +////////////////////////////////////////////////////////////////////////////// + +LogLevel +RootLogger::getChainedLogLevel() const +{ + return ll; +} + + +void +RootLogger::setLogLevel(LogLevel ll_) +{ + if(ll_ == NOT_SET_LOG_LEVEL) { + getLogLog().error(LOG4CPLUS_TEXT("You have tried to set NOT_SET_LOG_LEVEL to root.")); + } + else { + LoggerImpl::setLogLevel(ll_); + } +} + diff --git a/libs/log4cplus/src/sleep.cxx b/libs/log4cplus/src/sleep.cxx new file mode 100644 index 0000000..57cf56c --- /dev/null +++ b/libs/log4cplus/src/sleep.cxx @@ -0,0 +1,83 @@ +// Module: Log4CPLUS +// File: sleep.cxx +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 +#include + +#ifdef LOG4CPLUS_HAVE_ERRNO_H +#include +#endif + + +using namespace log4cplus; + + +/////////////////////////////////////////////////////////////////////////////// +// public methods +/////////////////////////////////////////////////////////////////////////////// + +int const MILLIS_TO_NANOS = 1000000; +int const SEC_TO_MILLIS = 1000; + + +void +log4cplus::helpers::sleep(unsigned long secs, unsigned long nanosecs) +{ +#if defined(_WIN32) + DWORD const MAX_SLEEP_SECONDS = 4294966; // (2**32-2)/1000 + + DWORD nano_millis = nanosecs / static_cast(MILLIS_TO_NANOS); + if (secs <= MAX_SLEEP_SECONDS) { + Sleep((secs * SEC_TO_MILLIS) + nano_millis); + return; + } + + DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; + + for(DWORD i = 0; i < no_of_max_sleeps; i++) { + Sleep(MAX_SLEEP_SECONDS * SEC_TO_MILLIS); + } + + Sleep((secs % MAX_SLEEP_SECONDS) * SEC_TO_MILLIS + nano_millis); +#else + timespec sleep_time = { secs, nanosecs }; + timespec remain; + while (nanosleep(&sleep_time, &remain)) { + if (errno == EINTR) { + sleep_time.tv_sec = remain.tv_sec; + sleep_time.tv_nsec = remain.tv_nsec; + continue; + } + else { + return; + } + } +#endif +} + + +void +log4cplus::helpers::sleepmillis(unsigned long millis) +{ + unsigned long secs = millis / SEC_TO_MILLIS; + unsigned long nanosecs = (millis % SEC_TO_MILLIS) * MILLIS_TO_NANOS; + sleep(secs, nanosecs); +} + diff --git a/libs/log4cplus/src/socket-unix.cxx b/libs/log4cplus/src/socket-unix.cxx new file mode 100644 index 0000000..b758d8c --- /dev/null +++ b/libs/log4cplus/src/socket-unix.cxx @@ -0,0 +1,338 @@ +// Module: Log4CPLUS +// File: socket-unix.cxx +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include + +#include + +#ifdef LOG4CPLUS_HAVE_NETINET_IN_H +#include +#endif + +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef LOG4CPLUS_HAVE_SYS_SOCKET_H +#include +#endif + +#include + +#ifdef LOG4CPLUS_HAVE_NETDB_H +#include +#endif + +#include + +#include +#include +#include + + +using namespace log4cplus; +using namespace log4cplus::helpers; + + +namespace +{ + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) +// We need to use log4cplus::thread here to work around compilation +// problem on AIX. +static log4cplus::thread::Mutex ghbn_mutex; + +#endif + + +static +int +get_host_by_name (char const * hostname, std::string * name, + struct sockaddr_in * addr) +{ +#if defined (LOG4CPLUS_HAVE_GETADDRINFO) + struct addrinfo hints; + std::memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_CANONNAME; + + if (inet_addr (hostname) != static_cast(-1)) + hints.ai_flags |= AI_NUMERICHOST; + + struct addrinfo * res = 0; + int ret = getaddrinfo (hostname, 0, &hints, &res); + if (ret != 0) + return ret; + + struct addrinfo const & ai = *res; + assert (ai.ai_family == AF_INET); + + if (name) + *name = ai.ai_canonname; + + if (addr) + std::memcpy (addr, ai.ai_addr, ai.ai_addrlen); + + freeaddrinfo (res); + +#else +# if ! defined (LOG4CPLUS_SINGLE_THREADED) + // We need to use log4cplus::thread here to work around + // compilation problem on AIX. + log4cplus::thread::MutexGuard guard (ghbn_mutex); +# endif + + struct ::hostent * hp = gethostbyname (hostname); + if (! hp) + return 1; + assert (hp->h_addrtype == AF_INET); + + if (name) + *name = hp->h_name; + + if (addr) + { + assert (hp->h_length <= sizeof (addr->sin_addr)); + std::memcpy (&addr->sin_addr, hp->h_addr_list[0], hp->h_length); + } + +#endif + + return 0; +} + + +} // namespace + + +///////////////////////////////////////////////////////////////////////////// +// Global Methods +///////////////////////////////////////////////////////////////////////////// + +SOCKET_TYPE +log4cplus::helpers::openSocket(unsigned short port, SocketState& state) +{ + SOCKET_TYPE sock = ::socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) { + return INVALID_SOCKET; + } + + struct sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(port); + + int optval = 1; + setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ); + + if(bind(sock, (struct sockaddr*)&server, sizeof(server)) < 0) { + return INVALID_SOCKET; + } + + if(::listen(sock, 10)) { + return INVALID_SOCKET; + } + + state = ok; + return sock; +} + + +SOCKET_TYPE +log4cplus::helpers::connectSocket(const log4cplus::tstring& hostn, + unsigned short port, SocketState& state) +{ + struct sockaddr_in server; + SOCKET_TYPE sock; + int retval; + + std::memset (&server, 0, sizeof (server)); + retval = get_host_by_name (LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str(), + 0, &server); + if (retval != 0) + return INVALID_SOCKET; + + server.sin_port = htons(port); + server.sin_family = AF_INET; + + sock = ::socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) { + return INVALID_SOCKET; + } + + while ((retval = ::connect(sock, + reinterpret_cast(&server), sizeof (server))) == -1 + && (errno == EINTR)) + ; + if(retval == INVALID_SOCKET) { + ::close(sock); + return INVALID_SOCKET; + } + + state = ok; + return sock; +} + + +namespace +{ + +//! Helper for accept_wrap(). +template +struct socklen_var +{ + typedef T type; +}; + + +template +struct socklen_var +{ + typedef U type; +}; + + +// Some systems like HP-UX have socklen_t but accept() does not use it +// as type of its 3rd parameter. This wrapper works around this +// incompatibility. +template +static +SOCKET_TYPE +accept_wrap ( + int (* accept_func) (int, accept_sockaddr_ptr_type, accept_socklen_type *), + SOCKET_TYPE sock, struct sockaddr * sa, socklen_t * len) +{ + typedef typename socklen_var::type + socklen_var_type; + socklen_var_type l = static_cast(*len); + SOCKET_TYPE result + = static_cast( + accept_func (sock, sa, + reinterpret_cast(&l))); + *len = static_cast(l); + return result; +} + + +} // namespace + + +SOCKET_TYPE +log4cplus::helpers::acceptSocket(SOCKET_TYPE sock, SocketState& state) +{ + struct sockaddr_in net_client; + socklen_t len = sizeof(struct sockaddr); + SOCKET_TYPE clientSock; + + while( (clientSock = accept_wrap (accept, sock, + (struct sockaddr*)&net_client, &len)) == -1 + && (errno == EINTR)) + ; + + if(clientSock != INVALID_SOCKET) { + state = ok; + } + + return clientSock; +} + + + +int +log4cplus::helpers::closeSocket(SOCKET_TYPE sock) +{ + return ::close(sock); +} + + + +long +log4cplus::helpers::read(SOCKET_TYPE sock, SocketBuffer& buffer) +{ + long read = 0; + + do + { + long res = ::read(sock, buffer.getBuffer() + read, + buffer.getMaxSize() - read); + if( res <= 0 ) { + return res; + } + read += res; + } while( read < static_cast(buffer.getMaxSize()) ); + + return read; +} + + + +long +log4cplus::helpers::write(SOCKET_TYPE sock, const SocketBuffer& buffer) +{ +#if defined(MSG_NOSIGNAL) + int flags = MSG_NOSIGNAL; +#else + int flags = 0; +#endif + return ::send( sock, buffer.getBuffer(), buffer.getSize(), flags ); +} + + +tstring +log4cplus::helpers::getHostname (bool fqdn) +{ + char const * hostname = "unknown"; + int ret; + std::vector hn (1024, 0); + + while (true) + { + ret = ::gethostname (&hn[0], static_cast(hn.size ()) - 1); + if (ret == 0) + { + hostname = &hn[0]; + break; + } +#if defined (LOG4CPLUS_HAVE_ENAMETOOLONG) + else if (ret != 0 && errno == ENAMETOOLONG) + // Out buffer was too short. Retry with buffer twice the size. + hn.resize (hn.size () * 2, 0); +#endif + else + break; + } + + if (ret != 0 || (ret == 0 && ! fqdn)) + return LOG4CPLUS_STRING_TO_TSTRING (hostname); + + std::string full_hostname; + ret = get_host_by_name (hostname, &full_hostname, 0); + if (ret == 0) + hostname = full_hostname.c_str (); + + return LOG4CPLUS_STRING_TO_TSTRING (hostname); +} + diff --git a/libs/log4cplus/src/socket-win32.cxx b/libs/log4cplus/src/socket-win32.cxx new file mode 100644 index 0000000..71261d5 --- /dev/null +++ b/libs/log4cplus/src/socket-win32.cxx @@ -0,0 +1,293 @@ +// Module: Log4CPLUS +// File: socket-win32.cxx +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include + + +using namespace log4cplus; +using namespace log4cplus::helpers; + + +///////////////////////////////////////////////////////////////////////////// +// file LOCAL Classes +///////////////////////////////////////////////////////////////////////////// + +namespace +{ + +enum WSInitStates +{ + WS_UNINITIALIZED, + WS_INITIALIZING, + WS_INITIALIZED +}; + + +static WSADATA wsa; +static LONG volatile winsock_state = WS_UNINITIALIZED; + + +static +void +init_winsock () +{ + // Quick check first to avoid the expensive interlocked compare + // and exchange. + if (winsock_state == WS_INITIALIZED) + return; + + // Try to change the state to WS_INITIALIZING. + LONG val = ::InterlockedCompareExchange ( + const_cast(&winsock_state), WS_INITIALIZING, WS_UNINITIALIZED); + switch (val) + { + case WS_UNINITIALIZED: + { + int ret = WSAStartup (MAKEWORD (2, 2), &wsa); + if (ret != 0) + { + // Revert the state back to WS_UNINITIALIZED to unblock other + // threads and let them throw exception. + val = ::InterlockedCompareExchange ( + const_cast(&winsock_state), WS_UNINITIALIZED, + WS_INITIALIZING); + assert (val == WS_INITIALIZING); + throw std::runtime_error ("Could not initialize WinSock."); + } + + // WinSock is initialized, change the state to WS_INITIALIZED. + val = ::InterlockedCompareExchange ( + const_cast(&winsock_state), WS_INITIALIZED, + WS_INITIALIZING); + assert (val == WS_INITIALIZING); + return; + } + + case WS_INITIALIZING: + // Wait for state change. + while (true) + { + switch (winsock_state) + { + case WS_INITIALIZED: + return; + + case WS_INITIALIZING: + ::Sleep (0); + continue; + + default: + assert (0); + throw std::runtime_error ("Unknown WinSock state."); + } + } + + case WS_INITIALIZED: + // WinSock is already initialized. + return; + + default: + assert (0); + throw std::runtime_error ("Unknown WinSock state."); + } +} + + +struct WinSockInitializer +{ + ~WinSockInitializer () + { + if (winsock_state == WS_INITIALIZED) + WSACleanup (); + } + + static WinSockInitializer winSockInitializer; +}; + + +WinSockInitializer WinSockInitializer::winSockInitializer; + + +} // namespace + + + +///////////////////////////////////////////////////////////////////////////// +// Global Methods +///////////////////////////////////////////////////////////////////////////// + +SOCKET_TYPE +log4cplus::helpers::openSocket(unsigned short port, SocketState& state) +{ + init_winsock (); + + SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0); + if(sock == INVALID_SOCKET) { + return sock; + } + + struct sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr.s_addr = htonl(INADDR_ANY); + server.sin_port = htons(port); + + if(bind(sock, (struct sockaddr*)&server, sizeof(server)) != 0) { + return INVALID_SOCKET; + } + + if(::listen(sock, 10) != 0) { + return INVALID_SOCKET; + } + + state = ok; + return sock; +} + + +SOCKET_TYPE +log4cplus::helpers::connectSocket(const log4cplus::tstring& hostn, + unsigned short port, SocketState& state) +{ + init_winsock (); + + SOCKET sock = ::socket(AF_INET, SOCK_STREAM, 0); + if(sock == INVALID_SOCKET) { + return INVALID_SOCKET; + } + + unsigned long ip = INADDR_NONE; + struct hostent *hp = ::gethostbyname( LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str() ); + if(hp == 0 || hp->h_addrtype != AF_INET) { + ip = inet_addr( LOG4CPLUS_TSTRING_TO_STRING(hostn).c_str() ); + if(ip == INADDR_NONE) { + state = bad_address; + return INVALID_SOCKET; + } + } + + struct sockaddr_in insock; + insock.sin_port = htons(port); + insock.sin_family = AF_INET; + if(hp != 0) { + memcpy(&insock.sin_addr, hp->h_addr, sizeof insock.sin_addr); + } + else { + insock.sin_addr.S_un.S_addr = ip; + } + + int retval; + while( (retval = ::connect(sock, (struct sockaddr*)&insock, sizeof(insock))) == -1 + && (WSAGetLastError() == WSAEINTR)) + ; + if(retval == SOCKET_ERROR) { + ::closesocket(sock); + return INVALID_SOCKET; + } + + int enabled = 1; + if(setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&enabled, sizeof(enabled)) != 0) { + ::closesocket(sock); + return INVALID_SOCKET; + } + + state = ok; + return sock; +} + + +SOCKET_TYPE +log4cplus::helpers::acceptSocket(SOCKET_TYPE sock, SocketState& /*state*/) +{ + init_winsock (); + + return ::accept(sock, NULL, NULL); +} + + + +int +log4cplus::helpers::closeSocket(SOCKET_TYPE sock) +{ + return ::closesocket(sock); +} + + + +long +log4cplus::helpers::read(SOCKET_TYPE sock, SocketBuffer& buffer) +{ + long read = 0; + + do + { + long res = ::recv(sock, buffer.getBuffer() + read, + static_cast(buffer.getMaxSize() - read), 0); + if( res <= 0 ) { + return res; + } + read += res; + } while( read < static_cast(buffer.getMaxSize()) ); + + return read; +} + + + +long +log4cplus::helpers::write(SOCKET_TYPE sock, const SocketBuffer& buffer) +{ + return ::send(sock, buffer.getBuffer(), static_cast(buffer.getSize()), 0); +} + + +tstring +log4cplus::helpers::getHostname (bool fqdn) +{ + char const * hostname = "unknown"; + int ret; + std::vector hn (1024, 0); + + while (true) + { + ret = ::gethostname (&hn[0], static_cast(hn.size ()) - 1); + if (ret == 0) + { + hostname = &hn[0]; + break; + } + else if (ret != 0 && WSAGetLastError () == WSAEFAULT) + // Out buffer was too short. Retry with buffer twice the size. + hn.resize (hn.size () * 2, 0); + else + break; + } + + if (ret != 0 || (ret == 0 && ! fqdn)) + return LOG4CPLUS_STRING_TO_TSTRING (hostname); + + struct ::hostent * hp = ::gethostbyname (hostname); + if (hp) + hostname = hp->h_name; + + return LOG4CPLUS_STRING_TO_TSTRING (hostname); +} diff --git a/libs/log4cplus/src/socket.cxx b/libs/log4cplus/src/socket.cxx new file mode 100644 index 0000000..f58a652 --- /dev/null +++ b/libs/log4cplus/src/socket.cxx @@ -0,0 +1,226 @@ +// Module: Log4CPLUS +// File: socket-win32.cxx +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 +#include + + +using namespace log4cplus; +using namespace log4cplus::helpers; + +#if !defined(_WIN32) +# include +# include +# define GET_LAST_ERROR errno +#else +# define GET_LAST_ERROR WSAGetLastError() +#endif + + + +////////////////////////////////////////////////////////////////////////////// +// AbstractSocket ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +log4cplus::helpers::AbstractSocket::AbstractSocket() +: sock(INVALID_SOCKET), + state(not_opened), + err(0) +{ +} + + + +log4cplus::helpers::AbstractSocket::AbstractSocket(SOCKET_TYPE sock_, SocketState state_, int err_) +: sock(sock_), + state(state_), + err(err_) +{ +} + + + +log4cplus::helpers::AbstractSocket::AbstractSocket(const log4cplus::helpers::AbstractSocket& rhs) +{ + copy(rhs); +} + + +log4cplus::helpers::AbstractSocket::~AbstractSocket() +{ + close(); +} + + + +////////////////////////////////////////////////////////////////////////////// +// AbstractSocket methods +////////////////////////////////////////////////////////////////////////////// + +void +log4cplus::helpers::AbstractSocket::close() +{ + if(sock != INVALID_SOCKET) { + closeSocket(sock); + sock = INVALID_SOCKET; + } +} + + + +bool +log4cplus::helpers::AbstractSocket::isOpen() const +{ + return sock != INVALID_SOCKET; +} + + + + +log4cplus::helpers::AbstractSocket& +log4cplus::helpers::AbstractSocket::operator=(const log4cplus::helpers::AbstractSocket& rhs) +{ + if(&rhs != this) { + close(); + copy(rhs); + } + + return *this; +} + + + +void +log4cplus::helpers::AbstractSocket::copy(const log4cplus::helpers::AbstractSocket& r) +{ + AbstractSocket& rhs = const_cast(r); + sock = rhs.sock; + state = rhs.state; + err = rhs.err; + rhs.sock = INVALID_SOCKET; + rhs.state = not_opened; + rhs.err = 0; +} + + + +////////////////////////////////////////////////////////////////////////////// +// Socket ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +log4cplus::helpers::Socket::Socket() +: AbstractSocket() +{ +} + + + +log4cplus::helpers::Socket::Socket(const tstring& address, int port) +: AbstractSocket() +{ + sock = connectSocket(address, port, state); + if(sock == INVALID_SOCKET) { + err = GET_LAST_ERROR; + } +} + + +log4cplus::helpers::Socket::Socket(SOCKET_TYPE sock_, SocketState state_, int err_) +: AbstractSocket(sock_, state_, err_) +{ +} + + + +log4cplus::helpers::Socket::~Socket() +{ +} + + + + + +////////////////////////////////////////////////////////////////////////////// +// Socket methods +////////////////////////////////////////////////////////////////////////////// + +bool +log4cplus::helpers::Socket::read(SocketBuffer& buffer) +{ + long retval = log4cplus::helpers::read(sock, buffer); + if(retval <= 0) { + close(); + } + else { + buffer.setSize(retval); + } + + return (retval > 0); +} + + + +bool +log4cplus::helpers::Socket::write(const SocketBuffer& buffer) +{ + long retval = log4cplus::helpers::write(sock, buffer); + if(retval <= 0) { + close(); + } + + return (retval > 0); +} + + + + +////////////////////////////////////////////////////////////////////////////// +// ServerSocket ctor and dtor +////////////////////////////////////////////////////////////////////////////// + +log4cplus::helpers::ServerSocket::ServerSocket(int port) +{ + sock = openSocket(port, state); + if(sock == INVALID_SOCKET) { + err = GET_LAST_ERROR; + } +} + + + +log4cplus::helpers::ServerSocket::~ServerSocket() +{ +} + + + +////////////////////////////////////////////////////////////////////////////// +// ServerSocket methods +////////////////////////////////////////////////////////////////////////////// + +log4cplus::helpers::Socket +log4cplus::helpers::ServerSocket::accept() +{ + SocketState state_; + SOCKET_TYPE clientSock = acceptSocket(sock, state_); + return Socket(clientSock, state_, 0); +} + + diff --git a/libs/log4cplus/src/socketappender.cxx b/libs/log4cplus/src/socketappender.cxx new file mode 100644 index 0000000..fcd5c49 --- /dev/null +++ b/libs/log4cplus/src/socketappender.cxx @@ -0,0 +1,326 @@ +// Module: Log4CPLUS +// File: socketappender.cxx +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include +#include +#include + + +int const LOG4CPLUS_MESSAGE_VERSION = 2; + + +namespace log4cplus +{ + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) +SocketAppender::ConnectorThread::ConnectorThread ( + SocketAppender & socket_appender) + : sa (socket_appender) + , exit_flag (false) +{ } + + +SocketAppender::ConnectorThread::~ConnectorThread () +{ } + + +void +SocketAppender::ConnectorThread::run () +{ + while (true) + { + trigger_ev.timed_wait (30 * 1000); + + getLogLog().debug ( + LOG4CPLUS_TEXT("SocketAppender::ConnectorThread::run()") + LOG4CPLUS_TEXT("- running...")); + + // Check exit condition as the very first thing. + + { + thread::Guard guard (access_mutex); + if (exit_flag) + return; + trigger_ev.reset (); + } + + // Do not try to re-open already open socket. + + { + thread::Guard guard (sa.access_mutex); + if (sa.socket.isOpen ()) + continue; + } + + // The socket is not open, try to reconnect. + + helpers::Socket socket (sa.host, sa.port); + if (! socket.isOpen ()) + { + getLogLog().error( + LOG4CPLUS_TEXT("SocketAppender::ConnectorThread::run()") + LOG4CPLUS_TEXT("- Cannot connect to server")); + + // Sleep for a short while after unsuccessful connection attempt + // so that we do not try to reconnect after each logging attempt + // which could be many times per second. + helpers::sleep (5); + + continue; + } + + // Connection was successful, move the socket into SocketAppender. + + { + thread::Guard guard (sa.access_mutex); + sa.socket = socket; + sa.connected = true; + } + } +} + + +void +SocketAppender::ConnectorThread::terminate () +{ + { + thread::Guard guard (access_mutex); + exit_flag = true; + trigger_ev.signal (); + } + join (); +} + + +void +SocketAppender::ConnectorThread::trigger () +{ + trigger_ev.signal (); +} + +#endif + + +////////////////////////////////////////////////////////////////////////////// +// SocketAppender ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +SocketAppender::SocketAppender(const tstring& host_, int port_, + const tstring& serverName_) +: host(host_), + port(port_), + serverName(serverName_) +{ + openSocket(); + initConnector (); +} + + + +SocketAppender::SocketAppender(const helpers::Properties & properties) + : Appender(properties), + port(9998) +{ + host = properties.getProperty( LOG4CPLUS_TEXT("host") ); + if(properties.exists( LOG4CPLUS_TEXT("port") )) { + tstring tmp = properties.getProperty( LOG4CPLUS_TEXT("port") ); + port = std::atoi(LOG4CPLUS_TSTRING_TO_STRING(tmp).c_str()); + } + serverName = properties.getProperty( LOG4CPLUS_TEXT("ServerName") ); + + openSocket(); + initConnector (); +} + + + +SocketAppender::~SocketAppender() +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + connector->terminate (); +#endif + + destructorImpl(); +} + + + +////////////////////////////////////////////////////////////////////////////// +// SocketAppender public methods +////////////////////////////////////////////////////////////////////////////// + +void +SocketAppender::close() +{ + getLogLog().debug(LOG4CPLUS_TEXT("Entering SocketAppender::close()...")); + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + connector->terminate (); +#endif + + socket.close(); + closed = true; +} + + + +////////////////////////////////////////////////////////////////////////////// +// SocketAppender protected methods +////////////////////////////////////////////////////////////////////////////// + +void +SocketAppender::openSocket() +{ + if(!socket.isOpen()) { + socket = helpers::Socket(host, port); + } +} + + +void +SocketAppender::initConnector () +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + connected = true; + connector = new ConnectorThread (*this); + connector->start (); +#endif +} + + +void +SocketAppender::append(const spi::InternalLoggingEvent& event) +{ +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + if (! connected) + { + connector->trigger (); + return; + } + +#else + if(!socket.isOpen()) { + openSocket(); + if(!socket.isOpen()) { + getLogLog().error(LOG4CPLUS_TEXT("SocketAppender::append()- Cannot connect to server")); + return; + } + } + +#endif + + helpers::SocketBuffer buffer = helpers::convertToBuffer(event, serverName); + helpers::SocketBuffer msgBuffer(LOG4CPLUS_MAX_MESSAGE_SIZE); + + msgBuffer.appendSize_t(buffer.getSize()); + msgBuffer.appendBuffer(buffer); + + bool ret = socket.write(msgBuffer); + if (! ret) + { +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + connected = false; + connector->trigger (); +#endif + } +} + + +///////////////////////////////////////////////////////////////////////////// +// namespace helpers methods +///////////////////////////////////////////////////////////////////////////// + +namespace helpers +{ + +SocketBuffer +convertToBuffer(const spi::InternalLoggingEvent& event, + const tstring& serverName) +{ + SocketBuffer buffer(LOG4CPLUS_MAX_MESSAGE_SIZE - sizeof(unsigned int)); + + buffer.appendByte(LOG4CPLUS_MESSAGE_VERSION); +#ifndef UNICODE + buffer.appendByte(1); +#else + buffer.appendByte(2); +#endif + + buffer.appendString(serverName); + buffer.appendString(event.getLoggerName()); + buffer.appendInt(event.getLogLevel()); + buffer.appendString(event.getNDC()); + buffer.appendString(event.getMessage()); + buffer.appendString(event.getThread()); + buffer.appendInt( static_cast(event.getTimestamp().sec()) ); + buffer.appendInt( static_cast(event.getTimestamp().usec()) ); + buffer.appendString(event.getFile()); + buffer.appendInt(event.getLine()); + + return buffer; +} + + +spi::InternalLoggingEvent +readFromBuffer(SocketBuffer& buffer) +{ + unsigned char msgVersion = buffer.readByte(); + if(msgVersion != LOG4CPLUS_MESSAGE_VERSION) { + SharedObjectPtr loglog = LogLog::getLogLog(); + loglog->warn(LOG4CPLUS_TEXT("readFromBuffer() received socket message with an invalid version")); + } + + unsigned char sizeOfChar = buffer.readByte(); + + tstring serverName = buffer.readString(sizeOfChar); + tstring loggerName = buffer.readString(sizeOfChar); + LogLevel ll = buffer.readInt(); + tstring ndc = buffer.readString(sizeOfChar); + if(! serverName.empty ()) { + if(ndc.empty ()) { + ndc = serverName; + } + else { + ndc = serverName + LOG4CPLUS_TEXT(" - ") + ndc; + } + } + tstring message = buffer.readString(sizeOfChar); + tstring thread = buffer.readString(sizeOfChar); + long sec = buffer.readInt(); + long usec = buffer.readInt(); + tstring file = buffer.readString(sizeOfChar); + int line = buffer.readInt(); + + return spi::InternalLoggingEvent(loggerName, + ll, + ndc, + message, + thread, + Time(sec, usec), + file, + line); +} + +} // namespace helpers + +} // namespace log4cplus diff --git a/libs/log4cplus/src/socketbuffer.cxx b/libs/log4cplus/src/socketbuffer.cxx new file mode 100644 index 0000000..6716ae6 --- /dev/null +++ b/libs/log4cplus/src/socketbuffer.cxx @@ -0,0 +1,345 @@ +// Module: Log4CPLUS +// File: socketbuffer.cxx +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2010 Tad E. Smith +// +// 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 +#include +#include +#include + +#if !defined(_WIN32) +# include +#else +#include +#endif + +#if defined (__CYGWIN__) || defined (LOG4CPLUS_HAVE_NETINET_IN_H) +#include +#endif + +using namespace log4cplus; +using namespace log4cplus::helpers; + + +////////////////////////////////////////////////////////////////////////////// +// SocketBuffer ctors and dtor +////////////////////////////////////////////////////////////////////////////// + +log4cplus::helpers::SocketBuffer::SocketBuffer(size_t maxsize_) +: maxsize(maxsize_), + size(0), + pos(0), + buffer(new char[maxsize_]) +{ +} + + + +log4cplus::helpers::SocketBuffer::SocketBuffer(const SocketBuffer& rhs) + : log4cplus::helpers::LogLogUser () +{ + copy(rhs); +} + + + +log4cplus::helpers::SocketBuffer::~SocketBuffer() +{ + delete [] buffer; +} + + + +SocketBuffer& +log4cplus::helpers::SocketBuffer::operator=(const SocketBuffer& rhs) +{ + if(&rhs != this) { + delete buffer; + copy(rhs); + } + + return *this; +} + + + +void +log4cplus::helpers::SocketBuffer::copy(const SocketBuffer& r) +{ + SocketBuffer& rhs = const_cast(r); + maxsize = rhs.maxsize; + size = rhs.size; + pos = rhs.pos; + buffer = rhs.buffer; + + rhs.maxsize = 0; + rhs.size = 0; + rhs.pos = 0; + rhs.buffer = 0; +} + + + + +////////////////////////////////////////////////////////////////////////////// +// SocketBuffer methods +////////////////////////////////////////////////////////////////////////////// + +unsigned char +log4cplus::helpers::SocketBuffer::readByte() +{ + if(pos >= maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readByte()- end of buffer reached")); + return 0; + } + else if((pos + sizeof(unsigned char)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readByte()- Attempt to read beyond end of buffer")); + return 0; + } + + unsigned char ret = *((unsigned char*)&buffer[pos]); + pos += sizeof(unsigned char); + + return ret; +} + + + +unsigned short +log4cplus::helpers::SocketBuffer::readShort() +{ + if(pos >= maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readShort()- end of buffer reached")); + return 0; + } + else if((pos + sizeof(unsigned short)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readShort()- Attempt to read beyond end of buffer")); + return 0; + } + + unsigned short ret; + std::memcpy(&ret, buffer + pos, sizeof(ret)); + ret = ntohs(ret); + pos += sizeof(unsigned short); + + return ret; +} + + + +unsigned int +log4cplus::helpers::SocketBuffer::readInt() +{ + if(pos >= maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readInt()- end of buffer reached")); + return 0; + } + else if((pos + sizeof(unsigned int)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readInt()- Attempt to read beyond end of buffer")); + return 0; + } + + unsigned int ret; + std::memcpy (&ret, buffer + pos, sizeof(ret)); + ret = ntohl(ret); + pos += sizeof(unsigned int); + + return ret; +} + + +tstring +log4cplus::helpers::SocketBuffer::readString(unsigned char sizeOfChar) +{ + size_t strlen = readInt(); + size_t bufferLen = strlen * sizeOfChar; + + if(strlen == 0) { + return tstring(); + } + if(pos > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readString()- end of buffer reached")); + return tstring(); + } + + if((pos + bufferLen) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readString()- Attempt to read beyond end of buffer")); + bufferLen = (maxsize - 1) - pos; + strlen = bufferLen / sizeOfChar; + } + +#ifndef UNICODE + if(sizeOfChar == 1) { + tstring ret(&buffer[pos], strlen); + pos += strlen; + return ret; + } + else if(sizeOfChar == 2) { + tstring ret; + for(tstring::size_type i=0; i(tmp < 256 ? tmp : ' '); + } + return ret; + } + else { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readString()- Invalid sizeOfChar!!!!")); + } + +#else /* UNICODE */ + if(sizeOfChar == 1) { + std::string ret(&buffer[pos], strlen); + pos += strlen; + return towstring(ret); + } + else if(sizeOfChar == 2) { + tstring ret; + for(tstring::size_type i=0; i(readShort()); + } + return ret; + } + else { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::readString()- Invalid sizeOfChar!!!!")); + } +#endif + + return tstring(); +} + + + +void +log4cplus::helpers::SocketBuffer::appendByte(unsigned char val) +{ + if((pos + sizeof(unsigned char)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendByte()- Attempt to write beyond end of buffer")); + return; + } + + *((unsigned char*)&buffer[pos]) = val; + pos += sizeof(unsigned char); + size = pos; +} + + + +void +log4cplus::helpers::SocketBuffer::appendShort(unsigned short val) +{ + if((pos + sizeof(unsigned short)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendShort()- Attempt to write beyond end of buffer")); + return; + } + + unsigned short s = htons(val); + std::memcpy(buffer + pos, &s, sizeof (s)); + pos += sizeof(s); + size = pos; +} + + + +void +log4cplus::helpers::SocketBuffer::appendInt(unsigned int val) +{ + if((pos + sizeof(unsigned int)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendInt()- Attempt to write beyond end of buffer")); + return; + } + + int i = htonl(val); + std::memcpy(buffer + pos, &i, sizeof (i)); + pos += sizeof(i); + size = pos; +} + + + +void +log4cplus::helpers::SocketBuffer::appendSize_t(size_t val) +{ + if ((pos + sizeof(unsigned)) > maxsize) + { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendInt(size_t)- ") + LOG4CPLUS_TEXT("Attempt to write beyond end of buffer")); + return; + } + if (val > (std::numeric_limits::max) ()) + { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendInt(size_t)-") + LOG4CPLUS_TEXT(" Attempt to write value greater than") + LOG4CPLUS_TEXT(" std::numeric_limits::max")); + return; + } + + unsigned st = htonl(static_cast(val)); + std::memcpy(buffer + pos, &st, sizeof(st)); + pos += sizeof(st); + size = pos; +} + + +void +log4cplus::helpers::SocketBuffer::appendString(const tstring& str) +{ +#ifndef UNICODE + size_t strlen = str.length(); + + if((pos + sizeof(unsigned int) + strlen) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendString()- Attempt to write beyond end of buffer")); + return; + } + + appendInt(static_cast(strlen)); + std::memcpy(&buffer[pos], str.data(), strlen); + pos += strlen; + size = pos; +#else + size_t strlen = str.length(); + + if((pos + sizeof(unsigned int) + (strlen * 2)) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendString()- Attempt to write beyond end of buffer")); + return; + } + + appendInt(static_cast(strlen)); + for(tstring::size_type i=0; i(str[i])); + } +#endif +} + + + +void +log4cplus::helpers::SocketBuffer::appendBuffer(const SocketBuffer& buf) +{ + if((pos + buf.getSize()) > maxsize) { + getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendBuffer()- Attempt to write beyond end of buffer")); + return; + } + + std::memcpy(&buffer[pos], buf.buffer, buf.getSize()); + pos += buf.getSize(); + size = pos; +} + + + diff --git a/libs/log4cplus/src/stringhelper.cxx b/libs/log4cplus/src/stringhelper.cxx new file mode 100644 index 0000000..20e6081 --- /dev/null +++ b/libs/log4cplus/src/stringhelper.cxx @@ -0,0 +1,407 @@ +// Module: Log4CPLUS +// File: stringhelper.cxx +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef UNICODE +# include +# include +#endif + +using namespace log4cplus; + +#if defined (LOG4CPLUS_SINGLE_THREADED) + +namespace log4cplus +{ + +tostringstream _macros_oss; + +namespace +{ + +static tostringstream const _macros_oss_defaults; +static tstring const _empty_str; + +} // namespace + +void _clear_tostringstream (tostringstream & os) +{ + os.clear (); + os.str (_empty_str); + os.setf (_macros_oss_defaults.flags ()); + os.fill (_macros_oss_defaults.fill ()); + os.precision (_macros_oss_defaults.precision ()); + os.width (_macros_oss_defaults.width ()); +#if defined (LOG4CPLUS_WORKING_LOCALE) + std::locale glocale = std::locale (); + if (os.getloc () != glocale) + os.imbue (glocale); +#endif // defined (LOG4CPLUS_WORKING_LOCALE) +} + +} // namespace log4cplus + +#endif + + +////////////////////////////////////////////////////////////////////////////// +// Global Methods +////////////////////////////////////////////////////////////////////////////// + +#ifdef UNICODE +log4cplus::tostream& +operator <<(log4cplus::tostream& stream, const char* str) +{ + return (stream << log4cplus::helpers::towstring(str)); +} + + +#ifdef LOG4CPLUS_WORKING_LOCALE + +static +void +clear_mbstate (std::mbstate_t & mbs) +{ + // Initialize/clear mbstate_t type. + // XXX: This is just a hack that works. The shape of mbstate_t varies + // from single unsigned to char[128]. Without some sort of initialization + // the codecvt::in/out methods randomly fail because the initial state is + // random/invalid. + ::memset (&mbs, 0, sizeof (std::mbstate_t)); +} + + +static +void +towstring_internal (std::wstring & outstr, const char * src, size_t size, + std::locale const & loc) +{ + if (size == 0) + { + outstr.clear (); + return; + } + + typedef std::codecvt CodeCvt; + const CodeCvt & cdcvt = std::use_facet(loc); + std::mbstate_t state; + clear_mbstate (state); + + char const * from_first = src; + size_t const from_size = size; + char const * const from_last = from_first + from_size; + char const * from_next = from_first; + + std::vector dest (from_size); + + wchar_t * to_first = &dest.front (); + size_t to_size = dest.size (); + wchar_t * to_last = to_first + to_size; + wchar_t * to_next = to_first; + + CodeCvt::result result; + size_t converted = 0; + while (true) + { + result = cdcvt.in ( + state, from_first, from_last, + from_next, to_first, to_last, + to_next); + // XXX: Even if only half of the input has been converted the + // in() method returns CodeCvt::ok. I think it should return + // CodeCvt::partial. + if ((result == CodeCvt::partial || result == CodeCvt::ok) + && from_next != from_last) + { + to_size = dest.size () * 2; + dest.resize (to_size); + converted = to_next - to_first; + to_first = &dest.front (); + to_last = to_first + to_size; + to_next = to_first + converted; + continue; + } + else if (result == CodeCvt::ok && from_next == from_last) + break; + else if (result == CodeCvt::error + && to_next != to_last && from_next != from_last) + { + clear_mbstate (state); + ++from_next; + from_first = from_next; + *to_next = L'?'; + ++to_next; + to_first = to_next; + } + else + break; + } + converted = to_next - &dest[0]; + + outstr.assign (dest.begin (), dest.begin () + converted); +} + + +std::wstring +log4cplus::helpers::towstring(const std::string& src, std::locale const & loc) +{ + std::wstring ret; + towstring_internal (ret, src.c_str (), src.size (), loc); + return ret; +} + + +std::wstring +log4cplus::helpers::towstring(char const * src, std::locale const & loc) +{ + std::wstring ret; + towstring_internal (ret, src, std::strlen (src), loc); + return ret; +} + + +static +void +tostring_internal (std::string & outstr, const wchar_t * src, size_t size, + std::locale const & loc) +{ + if (size == 0) + { + outstr.clear (); + return; + } + + typedef std::codecvt CodeCvt; + const CodeCvt & cdcvt = std::use_facet(loc); + std::mbstate_t state; + clear_mbstate (state); + + wchar_t const * from_first = src; + size_t const from_size = size; + wchar_t const * const from_last = from_first + from_size; + wchar_t const * from_next = from_first; + + std::vector dest (from_size); + + char * to_first = &dest.front (); + size_t to_size = dest.size (); + char * to_last = to_first + to_size; + char * to_next = to_first; + + CodeCvt::result result; + size_t converted = 0; + while (from_next != from_last) + { + result = cdcvt.out ( + state, from_first, from_last, + from_next, to_first, to_last, + to_next); + // XXX: Even if only half of the input has been converted the + // in() method returns CodeCvt::ok with VC8. I think it should + // return CodeCvt::partial. + if ((result == CodeCvt::partial || result == CodeCvt::ok) + && from_next != from_last) + { + to_size = dest.size () * 2; + dest.resize (to_size); + converted = to_next - to_first; + to_first = &dest.front (); + to_last = to_first + to_size; + to_next = to_first + converted; + } + else if (result == CodeCvt::ok && from_next == from_last) + break; + else if (result == CodeCvt::error + && to_next != to_last && from_next != from_last) + { + clear_mbstate (state); + ++from_next; + from_first = from_next; + *to_next = '?'; + ++to_next; + to_first = to_next; + } + else + break; + } + converted = to_next - &dest[0]; + + outstr.assign (dest.begin (), dest.begin () + converted); +} + + +std::string +log4cplus::helpers::tostring(const std::wstring& src, std::locale const & loc) +{ + std::string ret; + tostring_internal (ret, src.c_str (), src.size (), loc); + return ret; +} + + +std::string +log4cplus::helpers::tostring(wchar_t const * src, std::locale const & loc) +{ + std::string ret; + tostring_internal (ret, src, std::wcslen (src), loc); + return ret; +} + + +#else // LOG4CPLUS_WORKING_LOCALE + + +static +void +tostring_internal (std::string & ret, wchar_t const * src, size_t size) +{ + ret.resize(size); + for (size_t i = 0; i < size; ++i) + { + ret[i] = static_cast (static_cast (src[i])) < 256 + ? static_cast(src[i]) : '?'; + } +} + + +std::string +log4cplus::helpers::tostring(const std::wstring& src) +{ + std::string ret; + tostring_internal (ret, src.c_str (), src.size ()); + return ret; +} + + +std::string +log4cplus::helpers::tostring(wchar_t const * src) +{ + std::string ret; + tostring_internal (ret, src, std::wcslen (src)); + return ret; +} + + +static +void +towstring_internal (std::wstring & ret, char const * src, size_t size) +{ + ret.resize(size); + for (size_t i = 0; i < size; ++i) + { + ret[i] = static_cast + (static_cast (src[i])); + } +} + + +std::wstring +log4cplus::helpers::towstring(const std::string& src) +{ + std::wstring ret; + towstring_internal (ret, src.c_str (), src.size ()); + return ret; +} + + +std::wstring +log4cplus::helpers::towstring(char const * src) +{ + std::wstring ret; + towstring_internal (ret, src, std::strlen (src)); + return ret; +} + +#endif // LOG4CPLUS_WORKING_LOCALE + +#endif // UNICODE + + +namespace +{ + + +struct toupper_func +{ + tchar + operator () (tchar ch) const + { +#ifdef UNICODE +# if (defined(__MWERKS__) && defined(__MACOS__)) || defined (LOG4CPLUS_WORKING_LOCALE) + return std::towupper (ch); +# else + return ::towupper (ch); +# endif +#else + return ::toupper (static_cast(ch)); +#endif + } +}; + + +struct tolower_func +{ + tchar + operator () (tchar ch) const + { +#ifdef UNICODE +# if (defined(__MWERKS__) && defined(__MACOS__)) || defined (LOG4CPLUS_WORKING_LOCALE) + return std::towlower (ch); +# else + return ::towlower (ch); +# endif +#else + return ::tolower (static_cast(ch)); +#endif + } +}; + + +} // namespace + + +log4cplus::tstring +log4cplus::helpers::toUpper(const log4cplus::tstring& s) +{ + tstring ret; + std::transform(s.begin(), s.end(), + string_append_iterator(ret), toupper_func ()); + return ret; +} + + +log4cplus::tstring +log4cplus::helpers::toLower(const log4cplus::tstring& s) +{ + tstring ret; + std::transform(s.begin(), s.end(), + string_append_iterator(ret), tolower_func ()); + return ret; +} diff --git a/libs/log4cplus/src/syncprims.cxx b/libs/log4cplus/src/syncprims.cxx new file mode 100644 index 0000000..355d13c --- /dev/null +++ b/libs/log4cplus/src/syncprims.cxx @@ -0,0 +1,42 @@ +// Copyright (C) 2009, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + + +namespace log4cplus { namespace thread { namespace detail { + + +LOG4CPLUS_EXPORT +void +syncprims_throw_exception (char const * const msg, char const * const file, + int line) +{ + std::ostringstream oss; + oss << file << ":" << line << msg; + throw std::runtime_error (oss.str ()); +} + + +} } } // namespace log4cplus { namespace thread { namespace detail { diff --git a/libs/log4cplus/src/syslogappender.cxx b/libs/log4cplus/src/syslogappender.cxx new file mode 100644 index 0000000..1d06618 --- /dev/null +++ b/libs/log4cplus/src/syslogappender.cxx @@ -0,0 +1,244 @@ +// Module: Log4CPLUS +// File: syslogappender.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// Copyright 2001-2010 Tad E. Smith +// +// 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 +#if defined(LOG4CPLUS_HAVE_SYSLOG_H) && !defined(_WIN32) + +#include +#include +#include +#include + +#include + +using namespace std; +using namespace log4cplus::helpers; + + +namespace +{ + +static +const char* +useIdent (const std::string& string) +{ + if (string.empty ()) + return 0; + else + return string.c_str (); +} + + +static +int +parseFacility (const log4cplus::tstring& text) +{ + if (text.empty ()) + return 0; +#ifdef LOG_AUTH + else if (text == LOG4CPLUS_TEXT ("auth")) + return LOG_AUTH; +#endif +#ifdef LOG_AUTHPRIV + else if (text == LOG4CPLUS_TEXT ("authpriv")) + return LOG_AUTHPRIV; +#endif +#ifdef LOG_CRON + else if (text == LOG4CPLUS_TEXT ("cron")) + return LOG_CRON; +#endif +#ifdef LOG_DAEMON + else if (text == LOG4CPLUS_TEXT ("daemon")) + return LOG_DAEMON; +#endif +#ifdef LOG_FTP + else if (text == LOG4CPLUS_TEXT ("ftp")) + return LOG_FTP; +#endif +#ifdef LOG_KERN + else if (text == LOG4CPLUS_TEXT ("kern")) + return LOG_KERN; +#endif +#ifdef LOG_LOCAL0 + else if (text == LOG4CPLUS_TEXT ("local0")) + return LOG_LOCAL0; +#endif +#ifdef LOG_LOCAL1 + else if (text == LOG4CPLUS_TEXT ("local1")) + return LOG_LOCAL1; +#endif +#ifdef LOG_LOCAL2 + else if (text == LOG4CPLUS_TEXT ("local2")) + return LOG_LOCAL2; +#endif +#ifdef LOG_LOCAL3 + else if (text == LOG4CPLUS_TEXT ("local3")) + return LOG_LOCAL3; +#endif +#ifdef LOG_LOCAL4 + else if (text == LOG4CPLUS_TEXT ("local4")) + return LOG_LOCAL4; +#endif +#ifdef LOG_LOCAL5 + else if (text == LOG4CPLUS_TEXT ("local5")) + return LOG_LOCAL5; +#endif +#ifdef LOG_LOCAL6 + else if (text == LOG4CPLUS_TEXT ("local6")) + return LOG_LOCAL6; +#endif +#ifdef LOG_LOCAL7 + else if (text == LOG4CPLUS_TEXT ("local7")) + return LOG_LOCAL7; +#endif +#ifdef LOG_LPR + else if (text == LOG4CPLUS_TEXT ("lpr")) + return LOG_LPR; +#endif +#ifdef LOG_MAIL + else if (text == LOG4CPLUS_TEXT ("mail")) + return LOG_MAIL; +#endif +#ifdef LOG_NEWS + else if (text == LOG4CPLUS_TEXT ("news")) + return LOG_NEWS; +#endif +#ifdef LOG_SYSLOG + else if (text == LOG4CPLUS_TEXT ("syslog")) + return LOG_SYSLOG; +#endif +#ifdef LOG_USER + else if (text == LOG4CPLUS_TEXT ("user")) + return LOG_USER; +#endif +#ifdef LOG_UUCP + else if (text == LOG4CPLUS_TEXT ("uucp")) + return LOG_UUCP; +#endif + else + { + // Unknown facility. + log4cplus::tstring msg (LOG4CPLUS_TEXT ("Unknown syslog facility: ")); + msg += text; + log4cplus::helpers::LogLog::getLogLog ()->error (msg); + + return 0; + } +} + +} // namespace + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::SysLogAppender ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +log4cplus::SysLogAppender::SysLogAppender(const tstring& id) + : ident(id) + , facility (0) + // Store std::string form of ident as member of SysLogAppender so + // the address of the c_str() result remains stable for openlog & + // co to use even if we use wstrings. + , identStr(LOG4CPLUS_TSTRING_TO_STRING (id) ) +{ + ::openlog(useIdent(identStr), 0, 0); +} + + +log4cplus::SysLogAppender::SysLogAppender(const Properties & properties) + : Appender(properties) + , facility (0) +{ + ident = properties.getProperty( LOG4CPLUS_TEXT("ident") ); + facility = parseFacility ( + toLower (properties.getProperty (LOG4CPLUS_TEXT ("facility")))); + identStr = LOG4CPLUS_TSTRING_TO_STRING (ident); + ::openlog(useIdent(identStr), 0, 0); +} + + +log4cplus::SysLogAppender::~SysLogAppender() +{ + destructorImpl(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::SysLogAppender public methods +/////////////////////////////////////////////////////////////////////////////// + +void +log4cplus::SysLogAppender::close() +{ + getLogLog().debug(LOG4CPLUS_TEXT("Entering SysLogAppender::close()...")); + LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex ) + ::closelog(); + closed = true; + LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::SysLogAppender protected methods +/////////////////////////////////////////////////////////////////////////////// + +int +log4cplus::SysLogAppender::getSysLogLevel(const LogLevel& ll) const +{ + if(ll < DEBUG_LOG_LEVEL) { + return -1; + } + else if(ll < INFO_LOG_LEVEL) { + return LOG_DEBUG; + } + else if(ll < WARN_LOG_LEVEL) { + return LOG_INFO; + } + else if(ll < ERROR_LOG_LEVEL) { + return LOG_WARNING; + } + else if(ll < FATAL_LOG_LEVEL) { + return LOG_ERR; + } + else if(ll == FATAL_LOG_LEVEL) { + return LOG_CRIT; + } + + return LOG_ALERT; // ll > FATAL_LOG_LEVEL +} + + +// This method does not need to be locked since it is called by +// doAppend() which performs the locking +void +log4cplus::SysLogAppender::append(const spi::InternalLoggingEvent& event) +{ + int level = getSysLogLevel(event.getLogLevel()); + if(level != -1) { + log4cplus::tostringstream buf; + layout->formatAndAppend(buf, event); + ::syslog(facility | level, "%s", + LOG4CPLUS_TSTRING_TO_STRING(buf.str()).c_str()); + } +} + +#endif // defined(LOG4CPLUS_HAVE_SYSLOG_H) + diff --git a/libs/log4cplus/src/threads.cxx b/libs/log4cplus/src/threads.cxx new file mode 100644 index 0000000..185e897 --- /dev/null +++ b/libs/log4cplus/src/threads.cxx @@ -0,0 +1,331 @@ +// Module: Log4CPLUS +// File: threads.cxx +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2010 Tad E. Smith +// +// 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 LOG4CPLUS_SINGLE_THREADED + +#include +#include +#include +#include + +#include + +#ifdef LOG4CPLUS_HAVE_ERRNO_H +#include +#endif + +#if defined(LOG4CPLUS_USE_PTHREADS) +# include +# include +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) && ! defined (_WIN32_WCE) +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { namespace thread { + + +struct ThreadStart +{ +# ifdef LOG4CPLUS_USE_PTHREADS +static void* threadStartFuncWorker(void *); +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) && defined (_WIN32_WCE) +static DWORD threadStartFuncWorker(void *); +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) +static unsigned threadStartFuncWorker(void *); +# endif +}; + + +} } // namespace log4cplus { namespace thread { + + +namespace +{ + +# ifdef LOG4CPLUS_USE_PTHREADS +extern "C" void * threadStartFunc(void * param) +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) && defined (_WIN32_WCE) +static DWORD WINAPI threadStartFunc(void * param) +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) +static unsigned WINAPI threadStartFunc(void * param) +# endif +{ + return log4cplus::thread::ThreadStart::threadStartFuncWorker (param); +} + +} // namespace + + +namespace log4cplus { namespace thread { + + +/////////////////////////////////////////////////////////////////////////////// +// public methods +/////////////////////////////////////////////////////////////////////////////// + +LOG4CPLUS_MUTEX_PTR_DECLARE +createNewMutex() +{ +#if defined(LOG4CPLUS_USE_PTHREADS) + // The mutexes that we provide need to be recursive. This is + // because of double locking, first lock gets acquired in + // ConfigurationWatchDogThread::run() through the HierarchyLocker + // instance there. The second lock on appender_list_mutex is + // attempted in + // helpers::AppenderAttachableImpl::removeAllAppenders(). This + // results into deadlock on (at least) Linux. + + log4cplus::thread::PthreadMutexAttr mattr; + mattr.set_type (log4cplus::thread::Mutex::RECURSIVE); + + std::auto_ptr m (new pthread_mutex_t); + int ret = pthread_mutex_init (m.get (), &mattr.attr); + if (ret != 0) + throw std::runtime_error ("createNewMutex(): pthread_mutex_init () has failed."); + +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + std::auto_ptr< ::CRITICAL_SECTION> m (new ::CRITICAL_SECTION); + ::InitializeCriticalSection(m.get ()); + +#endif + + return m.release (); +} + + +void +deleteMutex(LOG4CPLUS_MUTEX_PTR_DECLARE m) +{ +#if defined(LOG4CPLUS_USE_PTHREADS) + ::pthread_mutex_destroy(m); +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + ::DeleteCriticalSection(m); +#endif + delete m; +} + + + +#if defined(LOG4CPLUS_USE_PTHREADS) +pthread_key_t* +createPthreadKey(void (*cleanupfunc)(void *)) +{ + ::pthread_key_t* key = new ::pthread_key_t; + ::pthread_key_create(key, cleanupfunc); + return key; +} +#endif + + +#ifndef LOG4CPLUS_SINGLE_THREADED +void +blockAllSignals() +{ +#if defined (LOG4CPLUS_USE_PTHREADS) + // Block all signals. + sigset_t signal_set; + sigfillset (&signal_set); + pthread_sigmask (SIG_BLOCK, &signal_set, 0); +#endif +} +#endif // LOG4CPLUS_SINGLE_THREADED + + +void +yield() +{ +#if defined(LOG4CPLUS_USE_PTHREADS) + sched_yield(); +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + ::Sleep(0); +#endif +} + + +tstring +getCurrentThreadName() +{ + tostringstream tmp; + tmp << LOG4CPLUS_GET_CURRENT_THREAD; + return tmp.str (); +} + + +#if defined(LOG4CPLUS_USE_PTHREADS) +void* +ThreadStart::threadStartFuncWorker(void * arg) +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) && defined (_WIN32_WCE) +DWORD +ThreadStart::threadStartFuncWorker(void * arg) +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) +unsigned +ThreadStart::threadStartFuncWorker(void * arg) +#endif +{ + blockAllSignals (); + helpers::SharedObjectPtr loglog + = helpers::LogLog::getLogLog(); + if (! arg) + loglog->error(LOG4CPLUS_TEXT("threadStartFunc()- arg is NULL")); + else + { + AbstractThread * ptr = static_cast(arg); + AbstractThreadPtr thread(ptr); + + // Decrease reference count increased by AbstractThread::start(). + ptr->removeReference (); + + try + { + thread->run(); + } + catch(std::exception& e) + { + tstring err = LOG4CPLUS_TEXT("threadStartFunc()- run() terminated with an exception: "); + err += LOG4CPLUS_C_STR_TO_TSTRING(e.what()); + loglog->warn(err); + } + catch(...) + { + loglog->warn(LOG4CPLUS_TEXT("threadStartFunc()- run() terminated with an exception.")); + } + thread->flags &= ~AbstractThread::fRUNNING; + getNDC().remove(); + } + + return 0; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// AbstractThread ctor and dtor +/////////////////////////////////////////////////////////////////////////////// + +AbstractThread::AbstractThread() + : flags (0) +#if defined(LOG4CPLUS_USE_WIN32_THREADS) + , handle (INVALID_HANDLE_VALUE) +#endif +{ +} + + + +AbstractThread::~AbstractThread() +{ +#if defined(LOG4CPLUS_USE_PTHREADS) + if ((flags & fJOINED) == 0) + pthread_detach (handle); + +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + if (handle != INVALID_HANDLE_VALUE) + ::CloseHandle (handle); + +#endif +} + + + +/////////////////////////////////////////////////////////////////////////////// +// AbstractThread public methods +/////////////////////////////////////////////////////////////////////////////// + +void +AbstractThread::start() +{ + flags |= fRUNNING; + + // Increase reference count here. It will be lowered by the running + // thread itself. + addReference (); + +#if defined(LOG4CPLUS_USE_PTHREADS) + if (pthread_create(&handle, NULL, threadStartFunc, this) ) + { + removeReference (); + flags &= ~fRUNNING; + throw std::runtime_error("Thread creation was not successful"); + } +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + HANDLE h = InterlockedExchangePointer (&handle, INVALID_HANDLE_VALUE); + if (h != INVALID_HANDLE_VALUE) + ::CloseHandle (h); + +#if defined (_WIN32_WCE) + h = ::CreateThread (0, 0, threadStartFunc, this, 0, &thread_id); +#else + h = reinterpret_cast( + ::_beginthreadex (0, 0, threadStartFunc, this, 0, &thread_id)); +#endif + if (! h) + { + removeReference (); + flags &= ~fRUNNING; + throw std::runtime_error("Thread creation was not successful"); + } + h = InterlockedExchangePointer (&handle, h); + assert (h == INVALID_HANDLE_VALUE); +#endif +} + + +LOG4CPLUS_THREAD_KEY_TYPE +AbstractThread::getThreadId () const +{ +#if defined(LOG4CPLUS_USE_PTHREADS) + return handle; +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + return thread_id; +#endif +} + + +LOG4CPLUS_THREAD_HANDLE_TYPE +AbstractThread::getThreadHandle () const +{ + return handle; +} + + +void +AbstractThread::join () +{ +#if defined(LOG4CPLUS_USE_PTHREADS) + pthread_join (handle, 0); +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) + ::WaitForSingleObject (handle, INFINITE); +#endif + flags |= fJOINED; +} + + +} } // namespace log4cplus { namespace thread { + +#endif // LOG4CPLUS_SINGLE_THREADED diff --git a/libs/log4cplus/src/timehelper.cxx b/libs/log4cplus/src/timehelper.cxx new file mode 100644 index 0000000..65df05b --- /dev/null +++ b/libs/log4cplus/src/timehelper.cxx @@ -0,0 +1,520 @@ +// Module: Log4CPLUS +// File: timehelper.cxx +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2009 Tad E. Smith +// +// 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#if ! defined (_WIN32_WCE) +#include +#endif +#if defined (UNICODE) +#include +#endif + +#if defined (LOG4CPLUS_HAVE_SYS_TYPES_H) +#include +#endif + +#if defined(LOG4CPLUS_HAVE_FTIME) +#include +#endif + +#if defined(LOG4CPLUS_HAVE_GETTIMEOFDAY) +#include +#endif + +#if defined(LOG4CPLUS_HAVE_GMTIME_R) && !defined(LOG4CPLUS_SINGLE_THREADED) +#define LOG4CPLUS_NEED_GMTIME_R +#endif + +#if defined(LOG4CPLUS_HAVE_LOCALTIME_R) && !defined(LOG4CPLUS_SINGLE_THREADED) +#define LOG4CPLUS_NEED_LOCALTIME_R +#endif + + +namespace log4cplus { namespace helpers { + +const int ONE_SEC_IN_USEC = 1000000; + + +#if defined (_WIN32_WCE) +using ::mktime; +using ::gmtime; +using ::localtime; +#if defined (UNICODE) +using ::wcsftime; +#else +using ::strftime; +#endif + +#else +using std::mktime; +using std::gmtime; +using std::localtime; +#if defined (UNICODE) +using std::wcsftime; +#else +using std::strftime; +#endif + +#endif + + + +////////////////////////////////////////////////////////////////////////////// +// Time ctors +////////////////////////////////////////////////////////////////////////////// + +Time::Time() +: tv_sec(0), + tv_usec(0) +{ +} + + +Time::Time(time_t tv_sec_, long tv_usec_) +: tv_sec(tv_sec_), + tv_usec(tv_usec_) +{ + assert (tv_usec < ONE_SEC_IN_USEC); +} + + +Time::Time(time_t time) +: tv_sec(time), + tv_usec(0) +{ +} + + +Time +Time::gettimeofday() +{ +#if defined (LOG4CPLUS_HAVE_CLOCK_GETTIME) + struct timespec ts; + int res = clock_gettime (CLOCK_REALTIME, &ts); + assert (res == 0); + if (res != 0) + throw std::runtime_error ("clock_gettime() has failed"); + + return Time (ts.tv_sec, ts.tv_nsec / 1000); +#elif defined(LOG4CPLUS_HAVE_GETTIMEOFDAY) + timeval tp; + ::gettimeofday(&tp, 0); + + return Time(tp.tv_sec, tp.tv_usec); +#elif defined(LOG4CPLUS_HAVE_FTIME) + struct timeb tp; + ::ftime(&tp); + + return Time(tp.time, tp.millitm * 1000); +#else +#warning "Time::gettimeofday()- low resolution timer: gettimeofday and ftime unavailable" + return Time(::time(0), 0); +#endif +} + + +////////////////////////////////////////////////////////////////////////////// +// Time methods +////////////////////////////////////////////////////////////////////////////// + +time_t +Time::setTime(tm* t) +{ + time_t time = helpers::mktime(t); + if (time != -1) + tv_sec = time; + + return time; +} + + +time_t +Time::getTime() const +{ + return tv_sec; +} + + +void +Time::gmtime(tm* t) const +{ + time_t clock = tv_sec; +#ifdef LOG4CPLUS_NEED_GMTIME_R + ::gmtime_r(&clock, t); +#else + tm* tmp = helpers::gmtime(&clock); + *t = *tmp; +#endif +} + + +void +Time::localtime(tm* t) const +{ + time_t clock = tv_sec; +#ifdef LOG4CPLUS_NEED_LOCALTIME_R + ::localtime_r(&clock, t); +#else + tm* tmp = helpers::localtime(&clock); + *t = *tmp; +#endif +} + + +namespace +{ + +static log4cplus::tstring const padding_zeros[4] = +{ + log4cplus::tstring (LOG4CPLUS_TEXT("000")), + log4cplus::tstring (LOG4CPLUS_TEXT("00")), + log4cplus::tstring (LOG4CPLUS_TEXT("0")), + log4cplus::tstring (LOG4CPLUS_TEXT("")) +}; + +static log4cplus::tstring const uc_q_padding_zeros[4] = +{ + log4cplus::tstring (LOG4CPLUS_TEXT(".000")), + log4cplus::tstring (LOG4CPLUS_TEXT(".00")), + log4cplus::tstring (LOG4CPLUS_TEXT(".0")), + log4cplus::tstring (LOG4CPLUS_TEXT(".")) +}; + +} + + +void +Time::build_q_value (log4cplus::tstring & q_str) const +{ + q_str = convertIntegerToString(tv_usec / 1000); + size_t const len = q_str.length(); + if (len <= 2) + q_str.insert (0, padding_zeros[q_str.length()]); +} + + +void +Time::build_uc_q_value (log4cplus::tstring & uc_q_str) const +{ + build_q_value (uc_q_str); + + log4cplus::tstring usecs (convertIntegerToString(tv_usec % 1000)); + size_t usecs_len = usecs.length(); + usecs.insert (0, usecs_len <= 3 + ? uc_q_padding_zeros[usecs_len] : uc_q_padding_zeros[3]); + uc_q_str.append (usecs); +} + + +log4cplus::tstring +Time::getFormattedTime(const log4cplus::tstring& fmt_orig, bool use_gmtime) const +{ + if (fmt_orig.empty () || fmt_orig[0] == 0) + return log4cplus::tstring (); + + tm time; + + if(use_gmtime) + gmtime(&time); + else + localtime(&time); + + enum State + { + TEXT, + PERCENT_SIGN + }; + + log4cplus::tstring fmt (fmt_orig); + log4cplus::tstring ret; + ret.reserve (static_cast(fmt.size () * 1.35)); + State state = TEXT; + + log4cplus::tstring q_str; + bool q_str_valid = false; + + log4cplus::tstring uc_q_str; + bool uc_q_str_valid = false; + + log4cplus::tstring s_str; + bool s_str_valid = false; + + // Walk the format string and process all occurences of %q and %Q. + + for (log4cplus::tstring::const_iterator fmt_it = fmt.begin (); + fmt_it != fmt.end (); ++fmt_it) + { + switch (state) + { + case TEXT: + { + if (*fmt_it == LOG4CPLUS_TEXT ('%')) + state = PERCENT_SIGN; + else + ret.push_back (*fmt_it); + } + break; + + case PERCENT_SIGN: + { + switch (*fmt_it) + { + case LOG4CPLUS_TEXT ('q'): + { + if (! q_str_valid) + { + build_q_value (q_str); + q_str_valid = true; + } + ret.append (q_str); + state = TEXT; + } + break; + + case LOG4CPLUS_TEXT ('Q'): + { + if (! uc_q_str_valid) + { + build_uc_q_value (uc_q_str); + uc_q_str_valid = true; + } + ret.append (uc_q_str); + state = TEXT; + } + break; + + // Windows do not support %s format specifier + // (seconds since epoch). + case LOG4CPLUS_TEXT ('s'): + { + if (! s_str_valid) + { + convertIntegerToString (s_str, tv_sec); + s_str_valid = true; + } + ret.append (s_str); + state = TEXT; + } + break; + + default: + { + ret.push_back (LOG4CPLUS_TEXT ('%')); + ret.push_back (*fmt_it); + state = TEXT; + } + } + } + break; + } + } + + // Finally call strftime/wcsftime to format the rest of the string. + + ret.swap (fmt); + size_t buffer_size = fmt.size () + 1; + std::vector buffer; + size_t len; + + // Limit how far can the buffer grow. This is necessary so that we + // catch bad format string. Some implementations of strftime() signal + // both too small buffer and invalid format string by returning 0 + // without changing errno. + size_t const buffer_size_max + = (std::max) (static_cast(1024), buffer_size * 16); + + do + { + buffer.resize (buffer_size); + errno = 0; +#ifdef UNICODE + len = helpers::wcsftime(&buffer[0], buffer_size, fmt.c_str(), &time); +#else + len = helpers::strftime(&buffer[0], buffer_size, fmt.c_str(), &time); +#endif + if (len == 0) + { + int const eno = errno; + buffer_size *= 2; + if (buffer_size > buffer_size_max) + { + log4cplus::tstring msg ( + LOG4CPLUS_TEXT ("Error in strftime(): ")); + msg += convertIntegerToString (eno); + LogLog::getLogLog ()->error (msg); + throw std::runtime_error (LOG4CPLUS_TSTRING_TO_STRING (msg)); + } + } + } + while (len == 0); + ret.assign (buffer.begin (), buffer.begin () + len); + + return ret; +} + + +Time& +Time::operator+=(const Time& rhs) +{ + tv_sec += rhs.tv_sec; + tv_usec += rhs.tv_usec; + + if(tv_usec > ONE_SEC_IN_USEC) { + ++tv_sec; + tv_usec -= ONE_SEC_IN_USEC; + } + + return *this; +} + + +Time& +Time::operator-=(const Time& rhs) +{ + tv_sec -= rhs.tv_sec; + tv_usec -= rhs.tv_usec; + + if(tv_usec < 0) { + --tv_sec; + tv_usec += ONE_SEC_IN_USEC; + } + + return *this; +} + + +Time& +Time::operator/=(long rhs) +{ + long rem_secs = static_cast(tv_sec % rhs); + tv_sec /= rhs; + + tv_usec /= rhs; + tv_usec += static_cast((rem_secs * ONE_SEC_IN_USEC) / rhs); + + return *this; +} + + +Time& +Time::operator*=(long rhs) +{ + long new_usec = tv_usec * rhs; + long overflow_sec = new_usec / ONE_SEC_IN_USEC; + tv_usec = new_usec % ONE_SEC_IN_USEC; + + tv_sec *= rhs; + tv_sec += overflow_sec; + + return *this; +} + + +////////////////////////////////////////////////////////////////////////////// +// Time globals +////////////////////////////////////////////////////////////////////////////// + + +const Time +operator+(const Time& lhs, const Time& rhs) +{ + return Time(lhs) += rhs; +} + + +const Time +operator-(const Time& lhs, const Time& rhs) +{ + return Time(lhs) -= rhs; +} + + +const Time +operator/(const Time& lhs, long rhs) +{ + return Time(lhs) /= rhs; +} + + +const Time +operator*(const Time& lhs, long rhs) +{ + return Time(lhs) *= rhs; +} + + +bool +operator<(const Time& lhs, const Time& rhs) +{ + return ( (lhs.sec() < rhs.sec()) + || ( (lhs.sec() == rhs.sec()) + && (lhs.usec() < rhs.usec())) ); +} + + +bool +operator<=(const Time& lhs, const Time& rhs) +{ + return ((lhs < rhs) || (lhs == rhs)); +} + + +bool +operator>(const Time& lhs, const Time& rhs) +{ + return ( (lhs.sec() > rhs.sec()) + || ( (lhs.sec() == rhs.sec()) + && (lhs.usec() > rhs.usec())) ); +} + + +bool +operator>=(const Time& lhs, const Time& rhs) +{ + return ((lhs > rhs) || (lhs == rhs)); +} + + +bool +operator==(const Time& lhs, const Time& rhs) +{ + return ( lhs.sec() == rhs.sec() + && lhs.usec() == rhs.usec()); +} + + +bool +operator!=(const Time& lhs, const Time& rhs) +{ + return !(lhs == rhs); +} + + +} } // namespace log4cplus { namespace helpers { diff --git a/libs/log4cplus/src/version.cxx b/libs/log4cplus/src/version.cxx new file mode 100644 index 0000000..504e39b --- /dev/null +++ b/libs/log4cplus/src/version.cxx @@ -0,0 +1,37 @@ +// Copyright (C) 2010, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + + +namespace log4cplus +{ + +#if ! defined (LOG4CPLUS_VERSION_STR_SUFFIX) +#define LOG4CPLUS_VERSION_STR_SUFFIX /* empty */ +#endif + +unsigned const version = LOG4CPLUS_VERSION; +char const versionStr[] = LOG4CPLUS_VERSION_STR LOG4CPLUS_VERSION_STR_SUFFIX; + +} diff --git a/libs/log4cplus/src/win32consoleappender.cxx b/libs/log4cplus/src/win32consoleappender.cxx new file mode 100644 index 0000000..e439e9b --- /dev/null +++ b/libs/log4cplus/src/win32consoleappender.cxx @@ -0,0 +1,177 @@ +// Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#include +#include +#include + + +#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) +namespace log4cplus +{ + + +Win32ConsoleAppender::Win32ConsoleAppender (bool allocConsole) + : alloc_console (allocConsole) +{ } + + +Win32ConsoleAppender::Win32ConsoleAppender ( + helpers::Properties const & properties) + : Appender (properties) + , alloc_console (true) +{ + tstring tmp = properties.getProperty (LOG4CPLUS_TEXT ("AllocConsole"), + LOG4CPLUS_TEXT ("true")); + alloc_console = helpers::toLower (tmp) == LOG4CPLUS_TEXT ("true"); +} + + +Win32ConsoleAppender::~Win32ConsoleAppender () +{ + destructorImpl(); +} + + +void +Win32ConsoleAppender::close () +{ + closed = true; +} + + +void +Win32ConsoleAppender::append (spi::InternalLoggingEvent const & event) +{ + if (alloc_console) + // We ignore the return value here. If we already have a console, + // it will fail. + AllocConsole (); + + HANDLE const console_out = GetStdHandle (STD_OUTPUT_HANDLE); + if (console_out == INVALID_HANDLE_VALUE) + { + getLogLog ().error ( + LOG4CPLUS_TEXT ("Win32ConsoleAppender::append") + LOG4CPLUS_TEXT ("- Unable to get STD_OUTPUT_HANDLE.")); + return; + } + + DWORD const handle_type = GetFileType (console_out); + if (handle_type == FILE_TYPE_UNKNOWN && GetLastError () != NO_ERROR) + { + getLogLog ().error ( + LOG4CPLUS_TEXT ("Win32ConsoleAppender::append") + LOG4CPLUS_TEXT ("- Error retrieving handle type.")); + return; + } + + tostringstream oss; + layout->formatAndAppend (oss, event); + tstring str = oss.str (); + size_t const str_len = str.size (); + tchar const * s = str.c_str (); + DWORD mode; + + if (handle_type == FILE_TYPE_CHAR && GetConsoleMode (console_out, &mode)) + // It seems that we have real console handle here. We can use + // WriteConsole() directly. + write_console (console_out, s, str_len); + else + // It seems that console is redirected. + write_handle (console_out, s, str_len); +} + + +void +Win32ConsoleAppender::write_handle (HANDLE out, tchar const * s, size_t str_len) +{ +#if defined (UNICODE) + std::wstring wstr (s, str_len); + std::string str (helpers::tostring (wstr)); + str_len = str.size (); + char const * const cstr = str.c_str (); + +#else + char const * const cstr = s; + +#endif + + DWORD const total_to_write = static_cast(str_len); + DWORD total_written = 0; + + do + { + DWORD const to_write = total_to_write - total_written; + DWORD written = 0; + + BOOL ret = WriteFile (out, cstr + total_written, to_write, &written, + 0); + if (! ret) + { + getLogLog ().error ( + LOG4CPLUS_TEXT ("Win32ConsoleAppender::write_handle") + LOG4CPLUS_TEXT ("- WriteFile has failed.")); + return; + } + + total_written += written; + } + while (total_written != total_to_write); +} + + +void +Win32ConsoleAppender::write_console (HANDLE console_out, tchar const * s, + size_t str_len) +{ + DWORD const total_to_write = static_cast(str_len); + DWORD total_written = 0; + + do + { + DWORD const to_write + = (std::min) (64*1024 - 1, total_to_write - total_written); + DWORD written = 0; + + BOOL ret = WriteConsole (console_out, s + total_written, to_write, + &written, 0); + if (! ret) + { + getLogLog ().error ( + LOG4CPLUS_TEXT ("Win32ConsoleAppender::write_console") + LOG4CPLUS_TEXT ("- WriteConsole has failed.")); + return; + } + + total_written += written; + } + while (total_written != total_to_write); +} + + + +} // namespace log4cplus + +#endif diff --git a/libs/log4cplus/src/win32debugappender.cxx b/libs/log4cplus/src/win32debugappender.cxx new file mode 100644 index 0000000..3b98c8a --- /dev/null +++ b/libs/log4cplus/src/win32debugappender.cxx @@ -0,0 +1,86 @@ +// Module: Log4CPLUS +// File: win32debugappender.cxx +// Created: 12/2003 +// Author: Eduardo Francos, Odalio SARL +// +// +// Copyright 2003-2010 Odalio SARL +// +// 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 + + +#if defined (LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING) + +using namespace std; +using namespace log4cplus; +using namespace log4cplus::helpers; + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::Win32DebugAppender ctors and dtor +/////////////////////////////////////////////////////////////////////////////// + +log4cplus::Win32DebugAppender::Win32DebugAppender() +{ +} + + +log4cplus::Win32DebugAppender::Win32DebugAppender( + const log4cplus::helpers::Properties& properties) + : Appender(properties) +{ +} + + + +log4cplus::Win32DebugAppender::~Win32DebugAppender() +{ + destructorImpl(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::Win32DebugAppender public methods +/////////////////////////////////////////////////////////////////////////////// + +void +log4cplus::Win32DebugAppender::close() +{ + closed = true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +// log4cplus::Win32DebugAppender protected methods +/////////////////////////////////////////////////////////////////////////////// + +// This method does not need to be locked since it is called by +// doAppend() which performs the locking +void +log4cplus::Win32DebugAppender::append(const spi::InternalLoggingEvent& event) +{ + tostringstream buf; + layout->formatAndAppend(buf, event); + tstring sz = buf.str(); + const tchar * s = sz.c_str(); + ::OutputDebugString(s); +} + + +#endif // LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING diff --git a/logging.cfg b/logging.cfg new file mode 100644 index 0000000..bd54507 --- /dev/null +++ b/logging.cfg @@ -0,0 +1,13 @@ +log4cplus.rootLogger=INFO, STDOUT, R + +log4cplus.appender.STDOUT=log4cplus::ConsoleAppender +log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout +log4cplus.appender.STDOUT.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n + +log4cplus.appender.R=log4cplus::RollingFileAppender +log4cplus.appender.R.File=gremlin.log +#log4cplus.appender.R.MaxFileSize=5MB +log4cplus.appender.R.MaxFileSize=500KB +log4cplus.appender.R.MaxBackupIndex=5 +log4cplus.appender.R.layout=log4cplus::TTCCLayout + diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 9eebd26..852a9e4 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -15,5 +15,5 @@ add_dependencies( gremlin ) target_link_libraries(gremlin - common enet glfw spark ${PLATFORM_LIBRARIES} ${OPENGL_LIBRARIES} + common enet glfw spark log4cplus ${PLATFORM_LIBRARIES} ${OPENGL_LIBRARIES} ) diff --git a/src/client/main.cpp b/src/client/main.cpp index 7d61f57..8c1ca82 100644 --- a/src/client/main.cpp +++ b/src/client/main.cpp @@ -1,8 +1,24 @@ +#include +#include + #include "Client.h" #include int main(int argc, const char **argv) { + log4cplus::BasicConfigurator basicConfig; + basicConfig.configure(); + + log4cplus::PropertyConfigurator propConfig("logging.cfg"); + propConfig.configure(); + + log4cplus::Logger logger = log4cplus::Logger::getInstance("main"); + LOG4CPLUS_INFO(logger, "starting gremlin"); + + LOG4CPLUS_INFO(logger, "arguments (" << argc << "):"); + for (size_t i = 0; i < argc; i++) + LOG4CPLUS_INFO(logger, " - " << argv[i]); + try { Client app; Arguments args(argc, argv); @@ -10,7 +26,6 @@ int main(int argc, const char **argv) { while (app.isRunning()) app.update(); app.shutdown(); - return 0; } catch (const char *str) { std::cerr << "Exception: " << str << std::endl; return 1; @@ -18,5 +33,7 @@ int main(int argc, const char **argv) { std::cerr << "Exception: " << e.what() << std::endl; return 1; } + + return 0; }