add log4cplus

This commit is contained in:
gmueller 2011-07-04 11:56:19 +02:00
parent d7abbcb5c7
commit dafe52c4cd
99 changed files with 18973 additions and 2 deletions

5
libs/log4cplus/AUTHORS Normal file
View File

@ -0,0 +1,5 @@
Tad E. Smith <tcsmith@users.sourceforge.net>
Michael CATANZARITI
Steighton Haley <baldheadedguy@users.sourceforge.net>
Eduardo Francos <gualo@users.sourceforge.net>
Vaclav Haisman <wilx@users.sourceforge.net>

View File

@ -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 ()

1
libs/log4cplus/COPYING Normal file
View File

@ -0,0 +1 @@
See the LICENSE file.

428
libs/log4cplus/ChangeLog Normal file
View File

@ -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:
<https://sourceforge.net/tracker/?func=browse&group_id=40830&atid=429073&artgroup=877523>
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 <sys/socket.h>
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.

365
libs/log4cplus/INSTALL Normal file
View File

@ -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 `<wchar.h>' 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.

452
libs/log4cplus/LICENSE Normal file
View File

@ -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.

1
libs/log4cplus/NEWS Normal file
View File

@ -0,0 +1 @@
See http://log4cplus.sourceforge.net/ for the latest news.

105
libs/log4cplus/README Normal file
View File

@ -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] <https://sourceforge.net/tracker/?func=detail&aid=3056687&group_id=40830&atid=429073>
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 <time.h> 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.

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/layout.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/logloguser.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/property.h>
#include <log4cplus/spi/filter.h>
#include <memory>
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<ErrorHandler> 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> 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 <b>Threshold</b> 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 <code>true</code>.
*/
bool isAsSevereAsThreshold(LogLevel ll) const {
return ((ll != NOT_SET_LOG_LEVEL) && (ll >= threshold));
}
protected:
// Methods
/**
* Subclasses of <code>Appender</code> 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> 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 <code>null</code>
* initially. */
log4cplus::spi::FilterPtr filter;
/** It is assumed and enforced that errorHandler is never null. */
std::auto_ptr<ErrorHandler> errorHandler;
/** Is this appender closed? */
bool closed;
};
/** This is a pointer to an Appender. */
typedef helpers::SharedObjectPtr<Appender> SharedAppenderPtr;
} // end namespace log4cplus
#endif // _LOG4CPLUS_APPENDER_HEADER_

View File

@ -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 <dlfcn.h> 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 <inttypes.h> 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 <memory.h> 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 <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> 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

View File

@ -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 <log4cplus/config/win32.h>
#elif (defined(__MWERKS__) && defined(__MACOS__))
# include <log4cplus/config/macosx.h>
#else
# include <log4cplus/config/defines.hxx>
#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 <log4cplus/helpers/thread-config.h>
#endif // LOG4CPLUS_CONFIG_HXX

View File

@ -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

View File

@ -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_

View File

@ -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 <windows.h>
#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: <type1> needs to have dll-interface to be used by clients of class <type2>
# pragma warning( disable : 4251 )
# if _MSC_VER >= 1400 && ! defined (_WIN32_WCE)
# define LOG4CPLUS_WORKING_LOCALE
# endif
#endif
#endif // _WIN32
#endif // LOG4CPLUS_CONFIG_WIN32_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#include <log4cplus/hierarchy.h>
#include <log4cplus/logger.h>
#include <log4cplus/helpers/logloguser.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/property.h>
#include <map>
namespace log4cplus
{
/**
* Provides configuration from an external file. See configure() for
* the expected format.
*
* <em>All option values admit variable substitution.</em> For
* example, if <code>userhome</code> environment property is set to
* <code>/home/xyz</code> and the File option is set to the string
* <code>${userhome}/test.log</code>, then File option will be
* interpreted as the string <code>/home/xyz/test.log</code>.
*
* The syntax of variable substitution is similar to that of UNIX
* shells. The string between an opening <b>&quot;${&quot;</b> and
* closing <b>&quot;}&quot;</b> 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
* <code>PropertyConfigurator</code> to configure log4cplus.
* It is equivalent to the following:<br>
* <code>
* PropertyConfigurator config("filename");
* config.configure();
* </code>
*/
static void doConfigure(const log4cplus::tstring& configFilename,
Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0);
/**
* Read configuration from a file. <b>The existing configuration is
* not cleared nor reset.</b> If you require a different behavior,
* then call {@link Hierarchy::resetConfiguration
* resetConfiguration} method before calling
* <code>doConfigure</code>.
*
* The configuration file consists of statements in the format
* <code>key=value</code>. The syntax of different configuration
* elements are discussed below.
*
* <h3>Appender configuration</h3>
*
* Appender configuration syntax is:
* <pre>
* # For appender named <i>appenderName</i>, 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
* </pre>
*
* For each named appender you can configure its {@link Layout}. The
* syntax for configuring an appender's layout is:
* <pre>
* log4cplus.appender.appenderName.layout=fully.qualified.name.of.layout.class
* log4cplus.appender.appenderName.layout.option1=value1
* ....
* log4cplus.appender.appenderName.layout.optionN=valueN
* </pre>
*
* <h3>Configuring loggers</h3>
*
* The syntax for configuring the root logger is:
* <pre>
* log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
* </pre>
*
* This syntax means that an optional <em>LogLevel value</em> 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 <em>custom LogLevel</em> 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 <i>appenderName</i> (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:
* <pre>
* log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
* </pre>
*
* 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 <i>appenderName</i>
* (separated by commas) will be attached to the named logger.
*
* See the <a href="../../../../manual.html#additivity">appender
* additivity rule</a> in the user manual for the meaning of the
* <code>additivity</code> flag.
*
* The user can override any of the {@link
* Hierarchy#disable} family of methods by setting the a key
* "log4cplus.disableOverride" to <code>true</code> or any value other
* than false. As in <pre>log4cplus.disableOverride=true </pre>
*
* <h3>Example</h3>
*
* An example configuration is given below.
*
* <pre>
*
* # 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
* # <b>%r %-5p %c{2} %M.%L %x - %m\n</b>. 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
* </pre>
*
* Refer to the <b>setOption</b> method in each Appender and
* Layout for class specific options.
*
* Use the <code>#</code> 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 <code>"log4cplus."</code>
* 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<log4cplus::tstring, log4cplus::SharedAppenderPtr> 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
* <code>rootLogger</code>, 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
* <code>BasicConfigurator</code> object to configure log4cplus.
* It is equivalent to the following:<br>
* <code><pre>
* BasicConfigurator config;
* config.configure();
* </pre></code>
*/
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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
namespace log4cplus {
/**
* ConsoleAppender appends log events to <code>std::cout</code> or
* <code>std::cerr</code> using a layout specified by the
* user. The default target is <code>std::cout</code>.
*
* <h3>Properties</h3>
* <dl>
* <dt><tt>logToStdErr</tt></dt>
* <dd>When it is set true, the output stream will be
* <code>std::cerr</code> instead of <code>std::cout</code>.</dd>
*
* <dt><tt>ImmediateFlush</tt></dt>
* <dd>When it is set true, output stream will be flushed after
* each appended event.</dd>
*
* </dl>
*/
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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#include <log4cplus/fstreams.h>
#include <log4cplus/helpers/property.h>
#include <log4cplus/helpers/timehelper.h>
#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.
*
* <h3>Properties</h3>
* <dl>
* <dt><tt>File</tt></dt>
* <dd>This property specifies output file name.</dd>
*
* <dt><tt>ImmediateFlush</tt></dt>
* <dd>When it is set true, output stream will be flushed after
* each appended event.</dd>
*
* <dt><tt>Append</tt></dt>
* <dd>When it is set true, output file will be appended to
* instead of being truncated at opening.</dd>
*
* <dt><tt>ReopenDelay</tt></dt>
* <dd>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.
* </dd>
*
* <dt><tt>BufferSize</tt></dt>
* <dd>Non-zero value of this property sets up buffering of output
* stream using a buffer of given size.
* </dd>
* </dl>
*/
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 <code>immediateFlush</code> is set to
* <code>false</code>, 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 <code>immediateFlush</code> variable is set to
* <code>true</code> by default.
*/
bool immediateFlush;
/**
* When any append operation fails, <code>reopenDelay</code> says
* for how many seconds the next attempt to re-open the log file and
* resume logging will be delayed. If <code>reopenDelay</code> is zero,
* each failed append operation will cause log file to be re-opened.
* By default, <code>reopenDelay</code> 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.
*
* <h3>Properties</h3>
* <p>Properties additional to {@link FileAppender}'s properties:
*
* <dl>
* <dt><tt>MaxFileSize</tt></dt>
* <dd>This property specifies maximal size of output file. The
* value is in bytes. It is possible to use <tt>MB</tt> and
* <tt>KB</tt> suffixes to specify the value in megabytes or
* kilobytes instead.</dd>
*
* <dt><tt>MaxBackupIndex</tt></dt>
* <dd>This property limits the number of backup output
* files; e.g. how many <tt>log.1</tt>, <tt>log.2</tt> etc. files
* will be kept.</dd>
* </dl>
*/
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.
*
* <h3>Properties</h3>
* <p>Properties additional to {@link FileAppender}'s properties:
*
* <dl>
* <dt><tt>Schedule</tt></dt>
* <dd>This property specifies rollover schedule. The possible
* values are <tt>MONTHLY</tt>, <tt>WEEKLY</tt>, <tt>DAILY</tt>,
* <tt>TWICE_DAILY</tt>, <tt>HOURLY</tt> and
* <tt>MINUTELY</tt>.</dd>
*
* <dt><tt>MaxBackupIndex</tt></dt>
* <dd>This property limits how many backup files are kept per
* single logging period; e.g. how many <tt>log.2009-11-07.1</tt>,
* <tt>log.2009-11-07.2</tt> etc. files are kept.</dd>
*
* </dl>
*/
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_

View File

@ -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 <log4cplus/config.hxx>
#include <fstream>
#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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/layout.h>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/logloguser.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/threads.h>
#include <log4cplus/spi/appenderattachable.h>
#include <memory>
#include <vector>
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 <code>name</code>.
*
* 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 <code>doAppend</code> method on all attached appenders.
*/
int appendLoopOnAppenders(const spi::InternalLoggingEvent& event) const;
protected:
// Types
typedef std::vector<SharedAppenderPtr> ListType;
// Data
/** Array of appenders. */
ListType appenderList;
}; // end class AppenderAttachableImpl
} // end namespace helpers
} // end namespace log4cplus
#endif // _LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/threads.h>
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
* <b>log4cplus.configDebug</b> variable.
*
* All log4cplus internal debug calls go to <code>cout</code>
* where as internal error messages are sent to
* <code>cerr</code>. 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 <code>LogLog</code> singleton.
*/
static log4cplus::helpers::SharedObjectPtr<LogLog> 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 <code>std::cout</code>.
*/
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 <code>std::cerr</code>.
*/
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 <code>std::cerr</code>.
*/
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

View File

@ -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 <log4cplus/config.hxx>
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

View File

@ -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 <log4cplus/config.hxx>
#include <memory>
#include <stdexcept>
#include <string>
#include <algorithm>
#include <cassert>
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 T>
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<T> (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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/streams.h>
#include <log4cplus/tstring.h>
#include <map>
#include <vector>
#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 <code>key</code> 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 <code>null</code> 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<log4cplus::tstring> propertyNames() const;
/**
* Inserts <code>value</code> into this map indexed by <code>key</code>.
*/
void setProperty(const log4cplus::tstring& key, const log4cplus::tstring& value);
/**
* Removed the property index by <code>key</code> 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<log4cplus::tstring, log4cplus::tstring>;
typedef std::map<log4cplus::tstring, log4cplus::tstring> StringMap;
// Methods
void init(log4cplus::tistream& input);
// Data
StringMap data;
};
} // end namespace helpers
}
#endif // LOG4CPLUS_HELPERS_PROPERTY_HEADER_

View File

@ -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 <log4cplus/config.hxx>
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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/socketbuffer.h>
#if defined(_WIN32)
#include <winsock.h>
#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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/logloguser.h>
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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <algorithm>
#include <limits>
#include <iterator>
namespace log4cplus {
namespace helpers {
/**
* Returns <code>s</code> in upper case.
*/
LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s);
/**
* Returns <code>s</code> in lower case.
*/
LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s);
/**
* Tokenize <code>s</code> using <code>c</code> as the delimiter and
* put the resulting tokens in <code>_result</code>. If
* <code>collapseTokens</code> is false, multiple adjacent delimiters
* will result in zero length tokens.
*
* <b>Example:</b>
* <pre>
* string s = // Set string with '.' as delimiters
* list<log4cplus::tstring> tokens;
* tokenize(s, '.', back_insert_iterator<list<string> >(tokens));
* </pre>
*/
template <class StringType, class OutputIter>
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 <typename intType, bool isSigned>
struct ConvertIntegerToStringHelper;
template <typename intType>
struct ConvertIntegerToStringHelper<intType, true>
{
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<intType>::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<tchar>(mod);
--it;
}
else
value = -value;
}
};
template <typename intType>
struct ConvertIntegerToStringHelper<intType, false>
{
static inline
void
step1 (tchar * &, intType &)
{
// This will never be called for unsigned types.
}
};
template<class intType>
inline
void
convertIntegerToString (tstring & str, intType value)
{
typedef std::numeric_limits<intType> intTypeLimits;
typedef ConvertIntegerToStringHelper<intType,
intTypeLimits::is_signed> 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<tchar>(mod);
}
if (negative)
{
--it;
*it = LOG4CPLUS_TEXT('-');
}
str.assign (static_cast<tchar const *>(it), buf_end);
}
template<class intType>
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 <code>push_back</code> method.
*/
template <class Container>
class string_append_iterator
: public std::iterator<std::output_iterator_tag, void, void, void,
void>
{
public:
typedef Container container_type;
explicit string_append_iterator(container_type & c)
: container(&c)
{ }
string_append_iterator<container_type> &
operator = (const typename container_type::value_type& value)
{
*container += value;
return *this;
}
string_append_iterator<container_type> &
operator * ()
{
return *this;
}
string_append_iterator<container_type> &
operator ++ ()
{
return *this;
}
string_append_iterator<container_type>
operator ++ (int)
{
return *this;
}
protected:
container_type * container;
};
} // namespace helpers
} // namespace log4cplus
#endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_

View File

@ -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 <limits>
#include <algorithm>
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<int>::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 {

View File

@ -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<DWORD>(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 {

View File

@ -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 <stdexcept>
#include <log4cplus/config.hxx>
#if defined (LOG4CPLUS_USE_PTHREADS)
# include <errno.h>
# include <pthread.h>
# include <semaphore.h>
# include <log4cplus/helpers/timehelper.h>
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
# undef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#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 <typename SP>
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<Mutex> 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<Semaphore> 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 <log4cplus/helpers/syncprims-pthreads.h>
#elif defined (LOG4CPLUS_USE_WIN32_THREADS)
# include <log4cplus/helpers/syncprims-win32.h>
#endif
namespace log4cplus { namespace thread {
//
//
//
template <typename SP>
inline
SyncGuard<SP>::SyncGuard (SP const & m)
: sp (&m)
{
sp->lock ();
}
template <typename SP>
inline
SyncGuard<SP>::~SyncGuard ()
{
if (sp)
sp->unlock ();
}
template <typename SP>
inline
void
SyncGuard<SP>::lock ()
{
sp->lock ();
}
template <typename SP>
inline
void
SyncGuard<SP>::unlock ()
{
sp->unlock ();
}
template <typename SP>
inline
void
SyncGuard<SP>::attach (SP const & m)
{
sp = &m;
}
template <typename SP>
inline
void
SyncGuard<SP>::detach ()
{
sp = 0;
}
} } // namespace log4cplus { namespace thread {
#endif // LOG4CPLUS_THREAD_SYNCPRIMS_H

View File

@ -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 <pthread.h>
# include <semaphore.h>
# 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 <windows.h>
# 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<LPVOID>(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
// <http://msdn.microsoft.com/en-us/library/2s9wt68x(vs.80).aspx>.
# 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/pointer.h>
namespace log4cplus { namespace thread {
/**
* This is used to lock a mutex. The dtor unlocks the mutex.
*/
class Guard
{
public:
/** "locks" <code>mutex</code>. */
Guard(LOG4CPLUS_MUTEX_PTR_DECLARE mutex)
: _mutex (mutex)
{
LOG4CPLUS_MUTEX_LOCK( _mutex );
}
/** "unlocks" <code>mutex</code>. */
~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<AbstractThread> AbstractThreadPtr;
#endif // LOG4CPLUS_SINGLE_THREADED
} } // namespace log4cplus { namespace thread {
#endif // _LOG4CPLUS_THREADS_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#if defined (LOG4CPLUS_HAVE_TIME_H)
//#include <time.h>
#endif
#if ! defined (_WIN32_WCE)
//#include <ctime>
#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 <code>gettimeofday()</code>
* method if it is available on the current platform. (Not on
* WIN32.)
*/
static Time gettimeofday();
// Methods
/**
* Returns <i>seconds</i> value.
*/
time_t sec() const { return tv_sec; }
/**
* Returns <i>microseconds</i> value.
*/
long usec() const { return tv_usec; }
/**
* Sets the <i>seconds</i> value.
*/
void sec(time_t s) { tv_sec = s; }
/**
* Sets the <i>microseconds</i> value.
*/
void usec(long us) { tv_usec = us; }
/**
* Sets this Time using the <code>mktime</code> function.
*/
time_t setTime(tm* t);
/**
* Returns this Time as a <code>time_t</code> value.
*/
time_t getTime() const;
/**
* Populates <code>tm</code> using the <code>gmtime()</code>
* function.
*/
void gmtime(tm* t) const;
/**
* Populates <code>tm</code> using the <code>localtime()</code>
* function.
*/
void localtime(tm* t) const;
/**
* Returns a string with a "formatted time" specified by
* <code>fmt</code>. It used the <code>strftime()</code>
* function to do this.
*
* Look at your platform's <code>strftime()</code> documentation
* for the formatting options available.
*
* The following additional options are provided:<br>
* <code>%q</code> - 3 character field that provides milliseconds
* <code>%Q</code> - 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/logger.h>
#include <log4cplus/helpers/logloguser.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/threads.h>
#include <map>
#include <memory>
#include <vector>
namespace log4cplus {
// Forward Declarations
class HierarchyLocker;
/**
* This class is specialized in retrieving loggers by name and
* also maintaining the logger hierarchy.
*
* <em>The casual user should not have to deal with this class
* directly.</em> 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 <em>really</em> know what you are doing before
* invoking this method.
*/
virtual void clear();
/**
* Returns <code>true </code>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 <em>equal to or
* below</em> the ll parameter <code>p</code>, for
* <em>all</em> loggers in this hierarchy. Logging requests of
* higher LogLevel then <code>p</code> 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 <a
* href="../../../../manual.html#selectionRule">Basic Selection Rule</a>.
*
* 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 <code>disable</code> 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
* <code>factory</code>.
*
* If a logger of that name already exists, then it will be
* returned. Otherwise, a new logger will be instantiated by the
* <code>factory</code> 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 <em>not</em> included in the returned list.
*/
virtual LoggerList getCurrentLoggers();
/**
* Is the LogLevel specified by <code>level</code> 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 <code>NOT_SET_LOG_LEVEL</code>,
* sets their additivity flag to <code>true</code> 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.</p>
*/
virtual void resetConfiguration();
/**
* Set the default LoggerFactory instance.
*/
virtual void setLoggerFactory(std::auto_ptr<spi::LoggerFactory> factory);
/**
* Returns the default LoggerFactory instance.
*/
virtual spi::LoggerFactory* getLoggerFactory() { return defaultFactory.get(); }
/**
* Shutting down a hierarchy will <em>safely</em> 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 <code>shutdown</code> 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<Logger> ProvisionNode;
typedef std::map<log4cplus::tstring, ProvisionNode> ProvisionNodeMap;
typedef std::map<log4cplus::tstring, Logger> LoggerMap;
// Methods
/**
* This is the implementation of the <code>getInstance()</code> method.
* NOTE: This method does not lock the <code>hashtable_mutex</code>.
*/
virtual Logger getInstanceImpl(const log4cplus::tstring& name,
spi::LoggerFactory& factory);
/**
* This is the implementation of the <code>getCurrentLoggers()</code>.
* NOTE: This method does not lock the <code>hashtable_mutex</code>.
*/
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<spi::LoggerFactory> 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_

View File

@ -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 <log4cplus/hierarchy.h>
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 <code>resetConfiguration()</code> method on the locked Hierarchy.
*/
void resetConfiguration();
/**
* Calls the <code>getInstance()</code> method on the locked Hierarchy.
*/
Logger getInstance(const log4cplus::tstring& name);
/**
* Calls the <code>getInstance()</code> 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/loglevel.h>
#include <log4cplus/streams.h>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/logloguser.h>
#include <log4cplus/helpers/property.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/spi/loggingevent.h>
#include <vector>
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,
*
* <pre>
* DEBUG - Hello world
* </pre>
*
* {@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 <code>DateFormat</code> used. Use the
* <code>Use_gmtime</code> to specify whether messages should be logged using
* <code>localtime</code> or <code>gmtime</code>.
*
* Here is an example TTCCLayout output:
*
* <pre>
* 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.
* </pre>
*
* 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 <em>conversion
* pattern</em>.
*
* 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
* <em>conversion specifiers</em>.
*
* <i>You are free to insert any literal text within the conversion
* pattern.</i>
*
* Each conversion specifier starts with a percent sign (%%) and is
* followed by optional <em>format modifiers</em> and a <em>conversion
* character</em>. 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 <b>"%-5p [%t]: %m%n"</b> and assume
* that the log4cplus environment was set to use a PatternLayout. Then the
* statements
* <code><pre>
* Logger root = Logger.getRoot();
* LOG4CPLUS_DEBUG(root, "Message 1");
* LOG4CPLUS_WARN(root, "Message 2");
* </pre></code>
* would yield the output
* <tt><pre>
* DEBUG [main]: Message 1
* WARN [main]: Message 2
* </pre></tt>
*
* 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
* <b>"%-5p"</b> means the LogLevel of the logging event should be left
* justified to a width of five characters.
*
* The recognized conversion characters are
*
*
* <table border="1" CELLPADDING="8">
* <tr>
* <td>Conversion Character</td>
* <td>Effect</td>
* </tr>
*
* <tr>
* <td align=center><b>b</b></td>
*
* <td>Used to output file name component of path name.
* E.g. <tt>main.cxx</tt> from path <tt>../../main.cxx</tt>.</td>
* </tr>
*
* <tr>
* <td align=center><b>c</b></td>
*
* <td>Used to output the logger of the logging event. The
* logger conversion specifier can be optionally followed by
* <em>precision specifier</em>, 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
* <b>%c{2}</b> will output "b.c".
*
* </td>
* </tr>
*
* <tr>
* <td align=center><b>d</b></td>
*
* <td>Used to output the date of the logging event in <b>UTC</b>.
*
* The date conversion specifier may be followed by a <em>date format
* specifier</em> enclosed between braces. For example, <b>%%d{%%H:%%M:%%s}</b>
* or <b>%%d{%%d&nbsp;%%b&nbsp;%%Y&nbsp;%%H:%%M:%%s}</b>. If no date format
* specifier is given then <b>%%d{%%d&nbsp;%%m&nbsp;%%Y&nbsp;%%H:%%M:%%s}</b>
* is assumed.
*
* The Following format options are possible:
* <ul>
* <li>%%a -- Abbreviated weekday name</li>
* <li>%%A -- Full weekday name</li>
* <li>%%b -- Abbreviated month name</li>
* <li>%%B -- Full month name</li>
* <li>%%c -- Standard date and time string</li>
* <li>%%d -- Day of month as a decimal(1-31)</li>
* <li>%%H -- Hour(0-23)</li>
* <li>%%I -- Hour(1-12)</li>
* <li>%%j -- Day of year as a decimal(1-366)</li>
* <li>%%m -- Month as decimal(1-12)</li>
* <li>%%M -- Minute as decimal(0-59)</li>
* <li>%%p -- Locale's equivalent of AM or PM</li>
* <li>%%q -- milliseconds as decimal(0-999) -- <b>Log4CPLUS specific</b>
* <li>%%Q -- fractional milliseconds as decimal(0-999.999) -- <b>Log4CPLUS specific</b>
* <li>%%S -- Second as decimal(0-59)</li>
* <li>%%U -- Week of year, Sunday being first day(0-53)</li>
* <li>%%w -- Weekday as a decimal(0-6, Sunday being 0)</li>
* <li>%%W -- Week of year, Monday being first day(0-53)</li>
* <li>%%x -- Standard date string</li>
* <li>%%X -- Standard time string</li>
* <li>%%y -- Year in decimal without century(0-99)</li>
* <li>%%Y -- Year including century as decimal</li>
* <li>%%Z -- Time zone name</li>
* <li>%% -- The percent sign</li>
* </ul>
*
* Lookup the documentation for the <code>strftime()</code> function
* found in the <code>&lt;ctime&gt;</code> header for more information.
* </td>
* </tr>
*
* <tr>
* <td align=center><b>D</b></td>
*
* <td>Used to output the date of the logging event in <b>local</b> time.
*
* All of the above information applies.
* </td>
* </tr>
*
* <tr>
* <td align=center><b>F</b></td>
*
* <td>Used to output the file name where the logging request was
* issued.
*
* <b>NOTE</b> Unlike log4j, there is no performance penalty for
* calling this method.
*
* </tr>
*
* <tr>
* <td align=center><b>h</b></td>
*
* <td>Used to output the hostname of this system (as returned
* by gethostname(2)).
*
* <b>NOTE</b> The hostname is only retrieved once at
* initialization.
*
* </td>
* </tr>
*
* <tr>
* <td align=center><b>H</b></td>
*
* <td>Used to output the fully-qualified domain name of this
* system (as returned by gethostbyname(2) for the hostname
* returned by gethostname(2)).
*
* <b>NOTE</b> The hostname is only retrieved once at
* initialization.
*
* </td>
* </tr>
*
* <tr>
* <td align=center><b>l</b></td>
*
* <td>Equivalent to using "%F:%L"
*
* <b>NOTE:</b> Unlike log4j, there is no performance penalty for
* calling this method.
*
* </td>
* </tr>
*
* <tr>
* <td align=center><b>L</b></td>
*
* <td>Used to output the line number from where the logging request
* was issued.
*
* <b>NOTE:</b> Unlike log4j, there is no performance penalty for
* calling this method.
*
* </tr>
*
*
* <tr>
* <td align=center><b>m</b></td>
* <td>Used to output the application supplied message associated with
* the logging event.</td>
* </tr>
*
* <tr>
* <td align=center><b>n</b></td>
*
* <td>Outputs the platform dependent line separator character or
* characters.
* </tr>
*
* <tr>
* <td align=center><b>p</b></td>
* <td>Used to output the LogLevel of the logging event.</td>
* </tr>
*
* <tr>
* <td align=center><b>t</b></td>
*
* <td>Used to output the name of the thread that generated the
* logging event.</td>
* </tr>
*
* <tr>
* <td align=center><b>i</b></td>
*
* <td>Used to output the process ID of the process that generated the
* logging event.</td>
* </tr>
*
* <tr>
* <td align=center><b>x</b></td>
*
* <td>Used to output the NDC (nested diagnostic context) associated
* with the thread that generated the logging event.
* </td>
* </tr>
*
* <tr>
* <td align=center><b>"%%"</b></td>
* <td>The sequence "%%" outputs a single percent sign.
* </td>
* </tr>
*
* </table>
*
* 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 <em>left justification
* flag</em> which is just the minus (-) character. Then comes the
* optional <em>minimum field width</em> 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 <em>maximum field
* width</em> 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
* <em>beginning</em> 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.
*
*
* <TABLE BORDER=1 CELLPADDING=8>
* <tr>
* <td>Format modifier</td>
* <td>left justify</td>
* <td>minimum width</td>
* <td>maximum width</td>
* <td>comment</td>
* </tr>
*
* <tr>
* <td align=center>%20c</td>
* <td align=center>false</td>
* <td align=center>20</td>
* <td align=center>none</td>
*
* <td>Left pad with spaces if the logger name is less than 20
* characters long.
* </tr>
*
* <tr> <td align=center>%-20c</td> <td align=center>true</td> <td
* align=center>20</td> <td align=center>none</td> <td>Right pad with
* spaces if the logger name is less than 20 characters long.
* </tr>
*
* <tr>
* <td align=center>%.30c</td>
* <td align=center>NA</td>
* <td align=center>none</td>
* <td align=center>30</td>
*
* <td>Truncate from the beginning if the logger name is longer than 30
* characters.
* </tr>
*
* <tr>
* <td align=center>%20.30c</td>
* <td align=center>false</td>
* <td align=center>20</td>
* <td align=center>30</td>
*
* <td>Left 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.
* </tr>
*
* <tr>
* <td align=center>%-20.30c</td>
* <td align=center>true</td>
* <td align=center>20</td>
* <td align=center>30</td>
*
* <td>Right 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.
* </tr>
*
* </table>
*
* Below are some examples of conversion patterns.
*
* <dl>
*
* <dt><b>"%r [%t] %-5p %c %x - %m%n"</b>
* <dd>This is essentially the TTCC layout.
*
* <dt><b>"%-6r [%15.15t] %-5p %30.30c %x - %m%n"</b>
*
* <dd>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.
*
* </dl>
*
* 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<pattern::PatternConverter*> parsedPattern;
private:
// Disallow copying of instances of this class
PatternLayout(const PatternLayout&);
PatternLayout& operator=(const PatternLayout&);
};
} // end namespace log4cplus
#endif // _LOG4CPLUS_LAYOUT_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/loglevel.h>
#include <log4cplus/tstring.h>
#include <log4cplus/spi/appenderattachable.h>
#include <log4cplus/spi/loggerfactory.h>
#include <vector>
namespace log4cplus
{
// Forward declarations
class Appender;
class Hierarchy;
class HierarchyLocker;
class DefaultLoggerFactory;
namespace spi
{
class LoggerImpl;
}
/** \typedef std::vector<Logger> LoggerList
* This is a list of {@link Logger Loggers}. */
typedef std::vector<Logger> 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 <a href="../../../../manual.html">user manual</a> for an
* introduction on this class.
*/
class LOG4CPLUS_EXPORT Logger
: public log4cplus::spi::AppenderAttachable
{
public:
// Static Methods
/**
* Returns <code>true </code>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 <em>not</em> included in the returned
* list.
*/
static LoggerList getCurrentLoggers();
/**
* Return the default Hierarchy instance.
*/
static Hierarchy& getDefaultHierarchy();
/**
* Retrieve a logger with name <code>name</code>. 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
* <code>factory</code> 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 <em>safely</em> 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 <code>shutdown</code> 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 <code>assertionVal</code> parameter is <code>false</code>, then
* logs <code>msg</code> with FATAL_LOG_LEVEL log level.
*
* @param assertionVal Truth value of assertion condition.
* @param msg The message to print if <code>assertion</code> 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 <code>ll</code>.
*/
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
* <code>this</code>. 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 <code>NOT_SET_LOG_LEVEL</code>.
*/
LogLevel getLogLevel() const;
/**
* Set the LogLevel of this Logger.
*/
void setLogLevel(LogLevel ll);
/**
* Return the the {@link Hierarchy} where this <code>Logger</code> 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 <code>Logger</code> 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 <code>"ENTER: " + msg</code>
* log message if TRACE_LOG_LEVEL is enabled for <code>logger</code>.
* When an instance of this class is destroyed, it will log a
* <code>"ENTER: " + msg</code> log message if TRACE_LOG_LEVEL is enabled
* for <code>logger</code>.
*
* @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 <log4cplus/loggingmacros.h>
#endif // _LOG4CPLUS_LOGGERHEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/streams.h>
#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 <code>logger</code> upon entry and
* exiting of a method.
* <code>logEvent</code> will be streamed into an <code>ostream</code>.
*/
#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 <code>logger</code>.
* <code>logEvent</code> will be streamed into an <code>ostream</code>.
*/
#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 <code>logger</code>.
* <code>logEvent</code> will be streamed into an <code>ostream</code>.
*/
#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 <code>logger</code>.
* <code>logEvent</code> will be streamed into an <code>ostream</code>.
*/
#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 <code>logger</code>.
* <code>logEvent</code> will be streamed into an <code>ostream</code>.
*/
#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 <code>logger</code>.
* <code>logEvent</code> will be streamed into an <code>ostream</code>.
*/
#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_ */

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <vector>
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 <code>OFF_LOG_LEVEL</code> LogLevel is used during configuration to
* turn off logging. */
const LogLevel OFF_LOG_LEVEL = 60000;
/** \var const LogLevel FATAL_LOG_LEVEL
* The <code>FATAL_LOG_LEVEL</code> 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 <code>ERROR_LOG_LEVEL</code> 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 <code>WARN_LOG_LEVEL</code> LogLevel designates potentially harmful
* situations. */
const LogLevel WARN_LOG_LEVEL = 30000;
/** \var const LogLevel INFO_LOG_LEVEL
* The <code>INFO_LOG_LEVEL</code> 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 <code>DEBUG_LOG_LEVEL</code> 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 <code>TRACE_LOG_LEVEL</code> LogLevel is used to "trace" entry
* and exiting of methods. */
const LogLevel TRACE_LOG_LEVEL = 0;
/** \var const LogLevel ALL_LOG_LEVEL
* The <code>ALL_LOG_LEVEL</code> 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 <code>NOT_SET_LOG_LEVEL</code> 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.
*
* <b>Note:</b> Must return an empty <code>tstring</code> for unrecognized values.
*/
typedef log4cplus::tstring (*LogLevelToStringMethod)(LogLevel);
/**
* This method type defined the signature of methods that convert strings
* into LogLevels.
*
* <b>Note:</b> Must return <code>NOT_SET_LOG_LEVEL</code> 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:
* <ol>
* <li>Create a LogLevel constant (greater than 0)</li>
* <li>Define a string to represent that constant</li>
* <li>Implement a LogLevelToStringMethod method.</li>
* <li>Implement a StringToLogLevelMethod method.</li>
* <li>create a "static initializer" that registers those 2 methods
* with the LogLevelManager singleton.</li>
* </ol>
*/
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 <code>LogLevelToStringMethod</code>
* 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 <code>StringToLogLevelMethod</code>
* to do this, so all "derived" LogLevels are recognized as well.
*/
LogLevel fromString(const log4cplus::tstring& s) const;
/**
* When creating a "derived" LogLevel, a <code>LogLevelToStringMethod</code>
* should be defined and registered with the LogLevelManager by calling
* this method.
*
* @see pushFromStringMethod
*/
void pushToStringMethod(LogLevelToStringMethod newToString);
/**
* When creating a "derived" LogLevel, a <code>StringToLogLevelMethod</code>
* 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/logloguser.h>
#include <map>
#include <stack>
#if (defined(__MWERKS__) && defined(__MACOS__))
using std::size_t;
#endif
namespace log4cplus {
// Forward declarations
class NDC;
struct DiagnosticContext;
typedef std::stack<DiagnosticContext> DiagnosticContextStack;
#if defined (_MSC_VER) || defined (__HP_aCC)
LOG4CPLUS_EXPORT NDC& getNDC();
#endif
/**
* The NDC class implements <i>nested diagnostic contexts</i> as
* defined by Neil Harrison in the article "Patterns for Logging
* Diagnostic Messages" part of the book "<i>Pattern Languages of
* Program Design 3</i>" 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.
*
* <em><b>Note that NDCs are managed on a per thread
* basis</b></em>. NDC operations such as {@link #push}, {@link
* #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth}
* affect the NDC of the <em>current</em> 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. <em>Cookies</em> are another source of distinctive
* information. To build an NDC one uses the {@link #push}
* operation. Simply put,
*
* <ul>
* <li>Contexts can be nested.
*
* <li>When entering a context, call <code>getNDC().push()</code>. As a
* side effect, if there is no nested diagnostic context for the
* current thread, this method will create it.
*
* <li>When leaving a context, call <code>getNDC().pop()</code>.
*
* <li><b>When exiting a thread make sure to call {@link #remove
* NDC.remove()}</b>.
* </ul>
*
* There is no penalty for forgetting to match each
* <code>push</code> operation with a corresponding <code>pop</code>,
* 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 <code>maxDepth</code> 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 <code>message</code> 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 <code>maxDepth</code>, 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 <code>setMaxDepth</code> method circumvents
* this problem.
*
* For example, the combination
* <pre>
* void foo() {
* &nbsp; size_t depth = NDC.getDepth();
*
* &nbsp; ... complex sequence of calls
*
* &nbsp; NDC.setMaxDepth(depth);
* }
* </pre>
*
* ensures that between the entry and exit of foo the depth of the
* diagnostic stack is conserved.
*
* <b>Note:</b> 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 <code>msg</code> onto the NDC stack. */
NDCContextCreator(const log4cplus::tstring& msg);
/** Pops the NDC stack. */
~NDCContextCreator();
};
} // end namespace log4cplus
#endif // _LO4CPLUS_NDC_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#include <log4cplus/helpers/property.h>
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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#include <log4cplus/helpers/socket.h>
#include <log4cplus/helpers/syncprims.h>
#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:
*
* <ul>
*
* <li>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.
*
* <li>SocketAppenders do not use a layout.
*
* <li>Remote logging uses the TCP protocol. Consequently, if
* the server is reachable, then log events will eventually arrive
* at the server.
*
* <li>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 <em>connector</em>
* thread which periodically attempts to connect to the server.
*
* <li>Logging events are automatically <em>buffered</em> 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.
*
* <li>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.
* </ul>
*
* <h3>Properties</h3>
* <dl>
* <dt><tt>host</tt></dt>
* <dd>Remote host name to connect and send events to.</dd>
*
* <dt><tt>port</tt></dt>
* <dd>Port on remote host to send events to.</dd>
*
* <dt><tt>ServerName</tt></dt>
* <dd>Host name of event's origin prepended to each event.</dd>
*
* </dl>
*/
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<ConnectorThread> 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/pointer.h>
#include <vector>
namespace log4cplus {
// Forward Declarations
typedef helpers::SharedObjectPtr<Appender> SharedAppenderPtr;
typedef std::vector<log4cplus::SharedAppenderPtr> 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/appender.h>
#include <log4cplus/layout.h>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/property.h>
#include <log4cplus/helpers/threads.h>
#include <log4cplus/spi/filter.h>
#include <log4cplus/spi/objectregistry.h>
#include <map>
#include <memory>
#include <vector>
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<Layout> ProductPtr;
LayoutFactory();
virtual ~LayoutFactory() = 0;
/**
* Create a "Layout" object.
*/
virtual std::auto_ptr<Layout> 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
* <code>put()</code> method. (The registry then owns the object.)
* These object can then be retrieved using the <code>get()</code>
* method.
*
* <b>Note:</b> This class is Thread-safe.
*/
template<class T>
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 <code>object</code>.)
*/
bool put(std::auto_ptr<T> 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<T*>(getVal(name));
}
protected:
virtual void deleteObject(void *object) const {
delete static_cast<T*>(object);
}
};
typedef FactoryRegistry<AppenderFactory> AppenderFactoryRegistry;
typedef FactoryRegistry<LayoutFactory> LayoutFactoryRegistry;
typedef FactoryRegistry<FilterFactory> FilterFactoryRegistry;
/**
* Returns the "singleton" <code>AppenderFactoryRegistry</code>.
*/
LOG4CPLUS_EXPORT AppenderFactoryRegistry& getAppenderFactoryRegistry();
/**
* Returns the "singleton" <code>LayoutFactoryRegistry</code>.
*/
LOG4CPLUS_EXPORT LayoutFactoryRegistry& getLayoutFactoryRegistry();
/**
* Returns the "singleton" <code>FilterFactoryRegistry</code>.
*/
LOG4CPLUS_EXPORT FilterFactoryRegistry& getFilterFactoryRegistry();
}
}
#endif // LOG4CPLUS_SPI_FACTORY_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/property.h>
#include <log4cplus/spi/loggingevent.h>
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: <code>filter</code> can be NULL.
*/
LOG4CPLUS_EXPORT FilterResult checkFilter(const Filter* filter,
const InternalLoggingEvent& event);
typedef helpers::SharedObjectPtr<Filter> 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 <code>filter</code> to the end of this filter chain.
*/
void appendFilter(FilterPtr filter);
/**
* If the decision is <code>DENY</code>, then the event will be
* dropped. If the decision is <code>NEUTRAL</code>, 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 <b>LogLevelToMatch</b> and
* <b>AcceptOnMatch</b>. 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 <b>AcceptOnMatch</b> option value is set
* to <code>true</code>, if it is <code>false</code> 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 <b>LogLevelToMatch</b>
* 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 <b>AcceptOnMatch</b> property is set to <code>true</code>.
* The returned decision is {@link #DENY} if the <b>AcceptOnMatch</b>
* property is set to <code>false</code>.
*/
virtual FilterResult decide(const InternalLoggingEvent& event) const;
private:
// Methods
void init();
// Data
/** Do we return ACCEPT when a match occurs. Default is <code>true</code>. */
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 <b>LogLevelMin</b>, <b>LogLevelMax</b>
* and <b>AcceptOnMatch</b>.
*
* 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
* <b>AcceptOnMatch</b> is true, {@link #ACCEPT} is returned, and if
* <b>AcceptOnMatch</b> is false, {@link #NEUTRAL} is returned.
*
* If <code>LogLevelMin</code> is not defined, then there is no
* minimum acceptable LogLevel (ie a LogLevel is never rejected for
* being too "low"/unimportant). If <code>LogLevelMax</code> 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 <code>all</code> 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 <code>true</code>. */
bool acceptOnMatch;
LogLevel logLevelMin;
LogLevel logLevelMax;
};
/**
* This is a very simple filter based on string matching.
*
* The filter admits two options <b>StringToMatch</b> and
* <b>AcceptOnMatch</b>. 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 <b>AcceptOnMatch</b> 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 <code>true</code>. */
bool acceptOnMatch;
log4cplus::tstring stringToMatch;
};
} // end namespace spi
} // end namespace log4cplus
#endif /* LOG4CPLUS_SPI_FILTER_HEADER_ */

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/pointer.h>
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 <code>Logger</code> 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

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/appenderattachableimpl.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/spi/loggerfactory.h>
#include <memory>
#include <vector>
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 <a href="../../../../manual.html">user manual</a> for an
* introduction on this class.
*/
class LOG4CPLUS_EXPORT LoggerImpl
: public virtual log4cplus::helpers::SharedObject,
public log4cplus::helpers::AppenderAttachableImpl
{
public:
typedef helpers::SharedObjectPtr<LoggerImpl> SharedLoggerImplPtr;
// Methods
/**
* Call the appenders in the hierrachy starting at
* <code>this</code>. 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 <code>ll</code>.
*/
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 <code>Logger</code>
* 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 <code>Logger</code> 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 <code>false</code> 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 <code>false</code> 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/loglevel.h>
#include <log4cplus/ndc.h>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/helpers/threads.h>
namespace log4cplus {
namespace spi {
/**
* The internal representation of logging events. When an affirmative
* decision is made to log then a <code>InternalLoggingEvent</code>
* 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 <code>filename</code> 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<InternalLoggingEvent> 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <log4cplus/helpers/threads.h>
#include <map>
#include <memory>
#include <vector>
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 <code>name</code>.
*/
bool exists(const log4cplus::tstring& name) const;
/**
* Returns the names of all registered objects.
*/
std::vector<log4cplus::tstring> getAllNames() const;
protected:
// Ctor and Dtor
ObjectRegistryBase();
virtual ~ObjectRegistryBase();
// protected methods
/**
* Used to enter an object into the registry. (The registry now
* owns <code>object</code>.)
*/
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 <code>object</code>.
*/
virtual void deleteObject(void *object) const = 0;
/**
* Deletes all objects from this registry.
*/
virtual void clear();
// Types
typedef std::map<log4cplus::tstring, void*> ObjectMap;
// Data
LOG4CPLUS_MUTEX_PTR_DECLARE mutex;
ObjectMap data;
};
}
}
#endif // LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggerimpl.h>
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 <code>NOT_SET_LOG_LEVEL</code>
* 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_

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/tstring.h>
#include <iostream>
#include <sstream>
#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_

View File

@ -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 <log4cplus/config.hxx>
#if defined(LOG4CPLUS_HAVE_SYSLOG_H) && !defined(_WIN32)
#include <log4cplus/appender.h>
namespace log4cplus {
/**
* Appends log events to a file.
*
* <h3>Properties</h3>
* <dl>
* <dt><tt>ident</tt></dt>
* <dd>First argument to <code>openlog()</code>, a string that
* will be prepended to every message.</dd>
*
* <dt><tt>facility</tt></dt>
* <dd>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.</dd>
* </dl>
*/
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_

View File

@ -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 <log4cplus/config.hxx>
#include <string>
#ifdef UNICODE
# ifdef LOG4CPLUS_WORKING_LOCALE
# include <locale>
# 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_

View File

@ -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 <log4cplus/config.hxx>
#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

View File

@ -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 <log4cplus/config.hxx>
#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE)
#include <log4cplus/appender.h>
#include <log4cplus/helpers/property.h>
namespace log4cplus
{
/**
* Prints events to Win32 console.
*
* <h3>Properties</h3>
* <dl>
* <dt><tt>AllocConsole</tt></dt>
* <dd>This boolean property specifies whether or not this appender
* will try to allocate new console using the
* <code>AllocConsole()</code> Win32 function.</dd>
*
* </dl>
*/
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

View File

@ -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 <log4cplus/config.hxx>
#if defined (LOG4CPLUS_HAVE_WIN32_CONSOLE)
#include <log4cplus/appender.h>
#include <log4cplus/helpers/property.h>
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_

View File

@ -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 <log4cplus/appender.h>
#include <log4cplus/layout.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/spi/factory.h>
#include <log4cplus/spi/loggingevent.h>
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<Layout> 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<ErrorHandler> 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<Layout> lo)
{
LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( access_mutex )
this->layout = lo;
LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX;
}
Layout*
Appender::getLayout()
{
return layout.get();
}

View File

@ -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 <log4cplus/appender.h>
#include <log4cplus/helpers/appenderattachableimpl.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#include <algorithm>
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

View File

@ -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 <log4cplus/configurator.h>
#include <log4cplus/hierarchylocker.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/helpers/property.h>
#include <log4cplus/helpers/syncprims.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/spi/factory.h>
#include <log4cplus/spi/loggerimpl.h>
#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef LOG4CPLUS_HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef LOG4CPLUS_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if defined (WIN32)
#include <tchar.h>
#endif
#if defined (_WIN32_WCE)
#include <windows.h>
#endif
#include <algorithm>
#include <vector>
#include <cstdlib>
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 <code>val</code> from
* environment variables.
*
* <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
*
* <p>For example, if the System properties contains "key=value", then
* the call
* <pre>
* string s;
* substEnvironVars(s, "Value of key is ${key}.");
* </pre>
*
* will set the variable <code>s</code> to "Value of key is value.".
*
* <p>If no value could be found for the specified key, then
* substitution defaults to the empty string.
*
* <p>For example, if there is no environment variable "inexistentKey",
* then the call
*
* <pre>
* string s;
* substEnvironVars(s, "Value of inexistentKey is [${inexistentKey}]");
* </pre>
* will set <code>s</code> 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<tstring> keys;
bool const rec_exp
= !! (flags & PropertyConfigurator::fRecursiveExpansion);
bool changed;
do
{
changed = false;
properties.propertyNames().swap (keys);
for (std::vector<tstring>::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<tstring> loggers = loggerProperties.propertyNames();
for(std::vector<tstring>::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<tstring>(configString),
std::bind1st(std::equal_to<tchar>(), LOG4CPLUS_TEXT(' ')));
// "Tokenize" configString
std::vector<tstring> 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<tstring>::size_type j=1; j<tokens.size(); ++j)
{
AppenderMap::iterator appenderIt = appenders.find(tokens[j]);
if (appenderIt == appenders.end())
{
getLogLog().error(
LOG4CPLUS_TEXT("PropertyConfigurator::configureLogger()")
LOG4CPLUS_TEXT("- Invalid appender: ")
+ tokens[j]);
continue;
}
addAppender(logger, appenderIt->second);
}
}
void
PropertyConfigurator::configureAppenders()
{
Properties appenderProperties =
properties.getPropertySubset(LOG4CPLUS_TEXT("appender."));
std::vector<tstring> appendersProps = appenderProperties.propertyNames();
tstring factoryName;
for(std::vector<tstring>::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<tstring> additivitysProps = additivityProperties.propertyNames();
tstring actualValue;
tstring value;
for(std::vector<tstring>::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

View File

@ -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 <log4cplus/layout.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/spi/loggingevent.h>
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;
}

View File

@ -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 <log4cplus/spi/factory.h>
#include <log4cplus/spi/loggerfactory.h>
#include <log4cplus/consoleappender.h>
#include <log4cplus/fileappender.h>
#include <log4cplus/nullappender.h>
#include <log4cplus/socketappender.h>
#include <log4cplus/syslogappender.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/threads.h>
#if defined (_WIN32)
# if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG)
# include <log4cplus/nteventlogappender.h>
# endif
# if defined (LOG4CPLUS_HAVE_WIN32_CONSOLE)
# include <log4cplus/win32consoleappender.h>
# endif
# include <log4cplus/Win32DebugAppender.h>
#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 <typename ProductFactoryBase>
class LocalFactoryBase
: public ProductFactoryBase
{
public:
LocalFactoryBase (tchar const * n)
: name (n)
{ }
virtual log4cplus::tstring getTypeName()
{
return name;
}
private:
log4cplus::tstring name;
};
template <typename LocalProduct, typename ProductFactoryBase>
class FactoryTempl
: public LocalFactoryBase<ProductFactoryBase>
{
public:
typedef typename ProductFactoryBase::ProductPtr ProductPtr;
FactoryTempl (tchar const * n)
: LocalFactoryBase<ProductFactoryBase> (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<productfact> ( \
new FactoryTempl<productns productname, productfact> ( \
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

View File

@ -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 <log4cplus/fileappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/spi/loggingevent.h>
#include <algorithm>
#include <cstdio>
#if defined (__BORLANDC__)
// For _wrename() and _wremove() on Windows.
# include <stdio.h>
#endif
#if ! defined (_WIN32_WCE)
#include <cerrno>
#endif
#include <cstdlib>
#if defined (_WIN32_WCE)
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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<helpers::LogLog> 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

View File

@ -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 <log4cplus/spi/filter.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
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);
}
}

View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/logger.h>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
// 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

View File

@ -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 <log4cplus/hierarchy.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggerimpl.h>
#include <log4cplus/spi/rootlogger.h>
#include <utility>
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<spi::LoggerFactory> 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<ProvisionNodeMap::iterator, bool> 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;
}
}
}

View File

@ -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 <log4cplus/hierarchylocker.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggerimpl.h>
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);
}

View File

@ -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 <log4cplus/layout.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/spi/loggingevent.h>
#include <iomanip>
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

View File

@ -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 <log4cplus/logger.h>
#include <log4cplus/appender.h>
#include <log4cplus/hierarchy.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggerimpl.h>
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

View File

@ -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 <log4cplus/spi/loggerimpl.h>
#include <log4cplus/appender.h>
#include <log4cplus/hierarchy.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/spi/rootlogger.h>
#include <stdexcept>
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));
}

View File

@ -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 <log4cplus/spi/loggingevent.h>
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>
InternalLoggingEvent::clone() const
{
std::auto_ptr<InternalLoggingEvent> 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;
}

View File

@ -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 <log4cplus/loglevel.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
#include <algorithm>
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<ToStringNode*>(this->toStringMethods)
#define GET_FROM_STRING_NODE static_cast<FromStringNode*>(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;
}
}
}

View File

@ -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 <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>
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>
LogLog::getLogLog()
{
static SharedObjectPtr<LogLog> 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;
}

View File

@ -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 <log4cplus/streams.h>
#include <log4cplus/helpers/logloguser.h>
#include <log4cplus/helpers/loglog.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
typedef SharedObjectPtr<LogLog> LogLogPtr;
///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::LogLogUser ctor and dtor
///////////////////////////////////////////////////////////////////////////////
LogLogUser::LogLogUser()
{
loglogRef = new SharedObjectPtr<LogLog>(LogLog::getLogLog());
}
LogLogUser::LogLogUser(const LogLogUser& rhs)
{
loglogRef = new SharedObjectPtr<LogLog>(*static_cast<LogLogPtr*>(rhs.loglogRef));
}
LogLogUser::~LogLogUser()
{
delete static_cast<LogLogPtr*>(loglogRef);
}
///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::LogLogUser public methods
///////////////////////////////////////////////////////////////////////////////
LogLog&
LogLogUser::getLogLog() const
{
LogLogPtr* ptr = static_cast<LogLogPtr*>(loglogRef);
return **ptr;
}
LogLogUser&
LogLogUser::operator=(const LogLogUser& rhs)
{
if(this == &rhs) {
return *this;
}
delete static_cast<LogLogPtr*>(loglogRef);
loglogRef = new SharedObjectPtr<LogLog>(*static_cast<LogLogPtr*>(rhs.loglogRef));
return *this;
}

329
libs/log4cplus/src/ndc.cxx Normal file
View File

@ -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 <log4cplus/config.hxx>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/pointer.h>
#include <exception>
#include <utility>
#include <vector>
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<DiagnosticContextStack*>
(LOG4CPLUS_GET_THREAD_LOCAL_VALUE( threadLocal ));
}
//
//
//
NDCContextCreator::NDCContextCreator(const log4cplus::tstring& msg)
{
getNDC().push(msg);
}
NDCContextCreator::~NDCContextCreator()
{
getNDC().pop();
}

View File

@ -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 <log4cplus/nteventlogappender.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#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<DWORD>(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

View File

@ -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 <log4cplus/nullappender.h>
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&)
{
}

View File

@ -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 <log4cplus/spi/objectregistry.h>
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::tstring>
log4cplus::spi::ObjectRegistryBase::getAllNames() const
{
std::vector<log4cplus::tstring> 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<ObjectMap::iterator, bool> 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;
}

View File

@ -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 <log4cplus/layout.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/helpers/socket.h>
#include <log4cplus/spi/loggingevent.h>
#ifdef LOG4CPLUS_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <exception>
#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef LOG4CPLUS_HAVE_UNISTD_H
#include <unistd.h>
#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.
* <p>
* @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<PatternConverter*> 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<PatternConverter*> list;
ParserState state;
tstring::size_type pos;
log4cplus::tstring currentLiteral;
unsigned ndcMaxDepth;
};
}
}
using namespace log4cplus::pattern;
typedef std::vector<log4cplus::pattern::PatternConverter*> 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<int>(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);
}
}

View File

@ -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 <log4cplus/streams.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/helpers/threads.h>
#include <assert.h>
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

View File

@ -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 <cstring>
#if defined (UNICODE)
# include <cwctype>
#else
# include <cctype>
#endif
#include <log4cplus/helpers/property.h>
#include <log4cplus/fstreams.h>
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<unsigned char>(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<tstring>
Properties::propertyNames() const
{
std::vector<tstring> 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<tstring> const keys = propertyNames();
size_t const prefix_len = prefix.size ();
for (std::vector<tstring>::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

View File

@ -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 <log4cplus/spi/rootlogger.h>
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_);
}
}

View File

@ -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 <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/timehelper.h>
#ifdef LOG4CPLUS_HAVE_ERRNO_H
#include <errno.h>
#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<unsigned long>(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);
}

View File

@ -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 <log4cplus/helpers/socket.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/threads.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/helpers/syncprims.h>
#include <arpa/inet.h>
#ifdef LOG4CPLUS_HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef LOG4CPLUS_HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <errno.h>
#ifdef LOG4CPLUS_HAVE_NETDB_H
#include <netdb.h>
#endif
#include <unistd.h>
#include <cstring>
#include <vector>
#include <algorithm>
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<in_addr_t>(-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<struct sockaddr *>(&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 <typename T, typename U>
struct socklen_var
{
typedef T type;
};
template <typename U>
struct socklen_var<void, U>
{
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 <typename accept_sockaddr_ptr_type, typename accept_socklen_type>
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<accept_socklen_type, socklen_t>::type
socklen_var_type;
socklen_var_type l = static_cast<socklen_var_type>(*len);
SOCKET_TYPE result
= static_cast<SOCKET_TYPE>(
accept_func (sock, sa,
reinterpret_cast<accept_socklen_type *>(&l)));
*len = static_cast<socklen_t>(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<long>(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<char> hn (1024, 0);
while (true)
{
ret = ::gethostname (&hn[0], static_cast<int>(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);
}

View File

@ -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 <cassert>
#include <vector>
#include <log4cplus/helpers/socket.h>
#include <log4cplus/helpers/loglog.h>
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<LPLONG>(&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<LPLONG>(&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<LPLONG>(&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<int>(buffer.getMaxSize() - read), 0);
if( res <= 0 ) {
return res;
}
read += res;
} while( read < static_cast<long>(buffer.getMaxSize()) );
return read;
}
long
log4cplus::helpers::write(SOCKET_TYPE sock, const SocketBuffer& buffer)
{
return ::send(sock, buffer.getBuffer(), static_cast<int>(buffer.getSize()), 0);
}
tstring
log4cplus::helpers::getHostname (bool fqdn)
{
char const * hostname = "unknown";
int ret;
std::vector<char> hn (1024, 0);
while (true)
{
ret = ::gethostname (&hn[0], static_cast<int>(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);
}

View File

@ -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 <log4cplus/helpers/socket.h>
#include <log4cplus/helpers/loglog.h>
using namespace log4cplus;
using namespace log4cplus::helpers;
#if !defined(_WIN32)
# include <errno.h>
# include <unistd.h>
# 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<AbstractSocket&>(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);
}

View File

@ -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 <cstdlib>
#include <log4cplus/socketappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/helpers/sleep.h>
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<unsigned int>(event.getTimestamp().sec()) );
buffer.appendInt( static_cast<unsigned int>(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 = 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

View File

@ -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 <cstring>
#include <limits>
#include <log4cplus/helpers/socketbuffer.h>
#include <log4cplus/helpers/loglog.h>
#if !defined(_WIN32)
# include <netdb.h>
#else
#include <winsock.h>
#endif
#if defined (__CYGWIN__) || defined (LOG4CPLUS_HAVE_NETINET_IN_H)
#include <netinet/in.h>
#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<SocketBuffer&>(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<strlen; ++i) {
unsigned short tmp = readShort();
ret += static_cast<char>(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<strlen; ++i) {
ret += static_cast<tchar>(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<unsigned>::max) ())
{
getLogLog().error(LOG4CPLUS_TEXT("SocketBuffer::appendInt(size_t)-")
LOG4CPLUS_TEXT(" Attempt to write value greater than")
LOG4CPLUS_TEXT(" std::numeric_limits<unsigned>::max"));
return;
}
unsigned st = htonl(static_cast<unsigned>(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<unsigned>(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<unsigned>(strlen));
for(tstring::size_type i=0; i<str.length(); ++i) {
appendShort(static_cast<unsigned short>(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;
}

View File

@ -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 <log4cplus/helpers/stringhelper.h>
#include <log4cplus/streams.h>
#include <log4cplus/loggingmacros.h>
#include <iterator>
#include <algorithm>
#include <cstring>
#include <cwchar>
#include <cwctype>
#include <cctype>
#ifdef UNICODE
# include <cassert>
# include <vector>
#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<wchar_t, char, std::mbstate_t> CodeCvt;
const CodeCvt & cdcvt = std::use_facet<CodeCvt>(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<wchar_t> 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<wchar_t, char, std::mbstate_t> CodeCvt;
const CodeCvt & cdcvt = std::use_facet<CodeCvt>(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<char> 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<unsigned> (static_cast<int> (src[i])) < 256
? static_cast<char>(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<wchar_t>
(static_cast<unsigned char> (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<unsigned char>(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<unsigned char>(ch));
#endif
}
};
} // namespace
log4cplus::tstring
log4cplus::helpers::toUpper(const log4cplus::tstring& s)
{
tstring ret;
std::transform(s.begin(), s.end(),
string_append_iterator<tstring>(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<tstring>(ret), tolower_func ());
return ret;
}

View File

@ -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 <sstream>
#include <log4cplus/helpers/syncprims.h>
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 {

View File

@ -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 <log4cplus/syslogappender.h>
#if defined(LOG4CPLUS_HAVE_SYSLOG_H) && !defined(_WIN32)
#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/spi/loggingevent.h>
#include <syslog.h>
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)

View File

@ -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 <cassert>
#include <exception>
#include <stdexcept>
#include <memory>
#include <log4cplus/config.hxx>
#ifdef LOG4CPLUS_HAVE_ERRNO_H
#include <errno.h>
#endif
#if defined(LOG4CPLUS_USE_PTHREADS)
# include <sched.h>
# include <signal.h>
#elif defined (LOG4CPLUS_USE_WIN32_THREADS) && ! defined (_WIN32_WCE)
# include <process.h>
#endif
#include <log4cplus/helpers/threads.h>
#include <log4cplus/streams.h>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
#include <log4cplus/helpers/timehelper.h>
#include <log4cplus/helpers/syncprims.h>
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<pthread_mutex_t> 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<helpers::LogLog> loglog
= helpers::LogLog::getLogLog();
if (! arg)
loglog->error(LOG4CPLUS_TEXT("threadStartFunc()- arg is NULL"));
else
{
AbstractThread * ptr = static_cast<AbstractThread*>(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<HANDLE>(
::_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

View File

@ -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 <log4cplus/helpers/timehelper.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/streams.h>
#include <log4cplus/helpers/stringhelper.h>
#include <ctime>
#include <algorithm>
#include <stdexcept>
#include <vector>
#include <iomanip>
#include <cassert>
#if ! defined (_WIN32_WCE)
#include <cerrno>
#endif
#if defined (UNICODE)
#include <cwchar>
#endif
#if defined (LOG4CPLUS_HAVE_SYS_TYPES_H)
#include <sys/types.h>
#endif
#if defined(LOG4CPLUS_HAVE_FTIME)
#include <sys/timeb.h>
#endif
#if defined(LOG4CPLUS_HAVE_GETTIMEOFDAY)
#include <sys/time.h>
#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<size_t>(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<tchar> 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<size_t>(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<long>(tv_sec % rhs);
tv_sec /= rhs;
tv_usec /= rhs;
tv_usec += static_cast<long>((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 {

View File

@ -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 <log4cplus/version.h>
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;
}

View File

@ -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 <log4cplus/win32consoleappender.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
#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<DWORD>(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<DWORD>(str_len);
DWORD total_written = 0;
do
{
DWORD const to_write
= (std::min<DWORD>) (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

View File

@ -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 <log4cplus/win32debugappender.h>
#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

13
logging.cfg Normal file
View File

@ -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

View File

@ -15,5 +15,5 @@ add_dependencies( gremlin
) )
target_link_libraries(gremlin target_link_libraries(gremlin
common enet glfw spark ${PLATFORM_LIBRARIES} ${OPENGL_LIBRARIES} common enet glfw spark log4cplus ${PLATFORM_LIBRARIES} ${OPENGL_LIBRARIES}
) )

View File

@ -1,8 +1,24 @@
#include <log4cplus/logger.h>
#include <log4cplus/configurator.h>
#include "Client.h" #include "Client.h"
#include <iostream> #include <iostream>
int main(int argc, const char **argv) { 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 { try {
Client app; Client app;
Arguments args(argc, argv); Arguments args(argc, argv);
@ -10,7 +26,6 @@ int main(int argc, const char **argv) {
while (app.isRunning()) while (app.isRunning())
app.update(); app.update();
app.shutdown(); app.shutdown();
return 0;
} catch (const char *str) { } catch (const char *str) {
std::cerr << "Exception: " << str << std::endl; std::cerr << "Exception: " << str << std::endl;
return 1; return 1;
@ -18,5 +33,7 @@ int main(int argc, const char **argv) {
std::cerr << "Exception: " << e.what() << std::endl; std::cerr << "Exception: " << e.what() << std::endl;
return 1; return 1;
} }
return 0;
} }